zoukankan      html  css  js  c++  java
  • fstab是什么?被谁用?怎么写?

    关键词:fstab、mount -a、fsck等等。

    1. fstab是干什么的?

    fstab是file system table的意思,即文件系统表。

    它在开机的时候告诉系统挂载哪些分区、挂载点是什么、以什么格式挂载、挂载的选项等等。

    然后系统在开机的时候就根据fstab内容,执行挂载操作。在挂载完之后,就可以在文件系统上进行操作。

    将需要挂载的分区放入fstab之后,就不需要手动挂载。

    2. fstab被谁调用?

    init进程在启动的时候会解析/etc/inittab文件,并执行其中选项。

    # /etc/inittab
    # Format for each entry: <id>:<runlevels>:<action>:<process>
    #
    # id        == tty to run on, or empty for /dev/console
    # runlevels == ignored
    # action    == one of sysinit, respawn, askfirst, wait, and once
    # process   == program to run
    ...
    ::sysinit:/bin/mount -a
    ...
    ::shutdown:/bin/umount -a -r

    其中mount -a执行Mount all filesystems in fstab,mount命令会解析fstab中内容,根据fstab配置执行相应关在操作。

    参考文档:《busybox启动流程简单解析:从init到shell login》。

    3. fstab如何生效?

    fstab是被mount命令解析,然后根据解析内容执行操作。

    mount命令将fstab中配置解析成一个struct mntent实例:

    struct mntent {
        char *mnt_fsname;---------------/* 挂载分区名称*/
        char *mnt_dir;------------------/* 挂载点*/
        char *mnt_type;-----------------/* 文件系统类型:ufs、nfs 等*/
        char *mnt_opts;-----------------/* 选项,以逗号为分隔符*/
        int mnt_freq;-------------------/* Dump 的频率(以天为单位)*/
        int mnt_passno;-----------------/* fsck检查的次序*/
    };

    操作struct mntent函数包括:

    setmntent():是打开包含挂载点项目的文件, 其中的 filename 参数是要打开的文件名, type 参数就像 fopen() 的第二个参数, 代表只读、只写, 或读写皆可的存取模式 。返回FILE*。
    getmntent():则是循序读取整个档案,传回指向 static struct mntent 结构的指针,结构中会填入适当的值。
    addmntent():可以在已开启档案的末端加上资讯,它原本是给 mount 使用的。
    endmntent():的功用是关闭打开的文件。这不能只是呼叫 fclose() 而已,因为可能还有其它与FILE * 有关的内部资料结构需要清理。

    这里主要分析mount -a的操作。

    int mount_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    int mount_main(int argc UNUSED_PARAM, char **argv)
    {
        char *cmdopts = xzalloc(1);
        char *fstype = NULL;
        char *O_optmatch = NULL;
        char *storage_path;
        llist_t *lst_o = NULL;
        const char *fstabname = "/etc/fstab";
        FILE *fstab;
        int i, j;
        int rc = EXIT_SUCCESS;
        unsigned long cmdopt_flags;
        unsigned opt;
        struct mntent mtpair[2], *mtcur = mtpair;
    ...
        for (i = j = 1; argv[i]; i++) {
            if (argv[i][0] == '-' && argv[i][1] == '-')
                append_mount_options(&cmdopts, argv[i] + 2);
            else
                argv[j++] = argv[i];
        }
        argv[j] = NULL;
    ...
        // Past this point, we are handling either "mount -a [opts]"
        // or "mount [opts] single_param"
    
        cmdopt_flags = parse_mount_options(cmdopts, NULL);
        if (nonroot && (cmdopt_flags & ~MS_SILENT)) // Non-root users cannot specify flags
            bb_error_msg_and_die(bb_msg_you_must_be_root);
    ...
        fstab = setmntent(fstabname, "r");------------------------------------------------fstabname默认指向/etc/fstab,打开fstab文件。
        if (!fstab)
            bb_perror_msg_and_die("can't read '%s'", fstabname);
    
        // Loop through entries until we find what we're looking for
        memset(mtpair, 0, sizeof(mtpair));
        for (;;) {
            struct mntent *mtother = (mtcur==mtpair ? mtpair+1 : mtpair);
    
            // Get next fstab entry
            if (!getmntent_r(fstab, mtcur, getmntent_buf----------------------------------从fstab中读取一条挂载信息放入mtcur中。
                        + (mtcur==mtpair ? GETMNTENT_BUFSIZE/2 : 0),
                    GETMNTENT_BUFSIZE/2)
            ) { // End of fstab/mtab is reached
                mtcur = mtother; // the thing we found last time
                break;
            }
            if (argv[0]) {
    
                // Is this what we're looking for?
                if (strcmp(argv[0], mtcur->mnt_fsname) != 0
                 && strcmp(storage_path, mtcur->mnt_fsname) != 0
                 && strcmp(argv[0], mtcur->mnt_dir) != 0
                 && strcmp(storage_path, mtcur->mnt_dir) != 0
                ) {
                    continue; // no
                }
                mtcur = mtother;
    
            // If we're mounting all
            } else {-----------------------------------------------------------------------mount -a相关路径。
                struct mntent *mp;
                // No, mount -a won't mount anything,
                // even user mounts, for mere humans
                if (nonroot)
                    bb_error_msg_and_die(bb_msg_you_must_be_root);
    
                // Does type match? (NULL matches always)
                if (!fstype_matches(mtcur->mnt_type, fstype))
                    continue;
    
                // Skip noauto and swap anyway
                if ((parse_mount_options(mtcur->mnt_opts, NULL) & (MOUNT_NOAUTO | MOUNT_SWAP))
                // swap is bogus "fstype", parse_mount_options can't check fstypes
                 || strcasecmp(mtcur->mnt_type, "swap") == 0
                ) {
                    continue;
                }
    
                // Does (at least one) option match?
                // (NULL matches always)
                if (!match_opt(mtcur->mnt_opts, O_optmatch))
                    continue;
                resolve_mount_spec(&mtcur->mnt_fsname);
    
                // NFS mounts want this to be xrealloc-able
                mtcur->mnt_opts = xstrdup(mtcur->mnt_opts);
    
                mp = find_mount_point(mtcur->mnt_dir, /*subdir_too:*/ 0);------------------检查mtcur->mnt_dir目录是否已经被mount。
                if (mp) {
                    if (verbose) {
                        bb_error_msg("according to %s, "
                            "%s is already mounted on %s",
                            bb_path_mtab_file,
                            mp->mnt_fsname, mp->mnt_dir);
                    }
                } else {
                    // ...mount this thing
                    if (singlemount(mtcur, /*ignore_busy:*/ 1)) {--------------------------执行mount操作。
                        // Count number of failed mounts
                        rc++;
                    }
                }
                free(mtcur->mnt_opts);
            }
        }
    ...
     //ret:
        if (ENABLE_FEATURE_CLEAN_UP)
            endmntent(fstab);
        if (ENABLE_FEATURE_CLEAN_UP) {
            free(storage_path);
            free(cmdopts);
        }
    
    //TODO: exitcode should be ORed mask of (from "man mount"):
    // 0 success
    // 1 incorrect invocation or permissions
    // 2 system error (out of memory, cannot fork, no more loop devices)
    // 4 internal mount bug or missing nfs support in mount
    // 8 user interrupt
    //16 problems writing or locking /etc/mtab
    //32 mount failure
    //64 some mount succeeded
        return rc;
    }

    singlemount()根据从fstab中解析的struct mntent,进行实际的mount操作。

    大部分类型的文件系统通过mount_it_now()进行挂载。

    4. fstab如何编写?

    fstab文件一行表示一个挂载操作,包含6列信息:<file system>、<mount pt>、<type>、<options>、<dump>、<pass>。

    # <file system>    <mount pt>    <type>    <options>    <dump>    <pass>
    /dev/root    /        ext2    rw,noauto    0    1
    proc        /proc        proc    defaults    0    0

    <file system>:表示磁盘文件、设备的Label或者UUID。设备的Label和UUID都可以通过dumpe2fs -h /dev/xxxx查看。使用UUID可以唯一标识一个分区,不会因为磁盘插槽顺序改变错误挂载。

    <mount pt>:是设备挂载点,就是设备要挂载到哪个目录下。

    <type>:待挂载的文件系统格式。

    <options>:挂载时的选项。

    Async/sync 设置是否为同步方式运行,默认为async
    auto/noauto 当下载mount -a 的命令时,此文件系统是否被主动挂载。默认为auto
    rw/ro 是否以以只读或者读写模式挂载
    exec/noexec 限制此文件系统内是否能够进行”执行”的操作
    user/nouser 是否允许用户使用mount命令挂载
    suid/nosuid 是否允许SUID的存在
    Usrquota 启动文件系统支持磁盘配额模式
    Grpquota 启动文件系统对群组磁盘配额模式的支持
    Defaults 同时具有rw,suid,dev,exec,auto,nouser,async等默认参数的设置

    <dump>:是否被dump命令使用:

    0 代表不要做dump备份
    1 代表要每天进行dump的操作
    2 代表不定日期的进行dump操作

    <pass>:标识是否检验扇区,在开机过程中,系统默认会以fsck检查系统是否完整。

    0 不要检验
    1 最早检验(一般根目录会选择)
    2 1级别检验完成之后进行检验

    5. 小结

    fstab被mount -a命令解析,然后针对不同文件系统类型将设备挂载到指定目录。

    如果需要将某一个设备在开机是挂在到系统中,需要通过编写fstab即可,共6列需要配置。

    修改fstab之后,通过mount -a立即生效,或者通过重启生效。

    参考文档:《A complete fstab guide》、《Linux命令-自动挂载文件/etc/fstab功能详解[转]》。

  • 相关阅读:
    希腊字母写法
    The ASP.NET MVC request processing line
    lambda aggregation
    UVA 10763 Foreign Exchange
    UVA 10624 Super Number
    UVA 10041 Vito's Family
    UVA 10340 All in All
    UVA 10026 Shoemaker's Problem
    HDU 3683 Gomoku
    UVA 11210 Chinese Mahjong
  • 原文地址:https://www.cnblogs.com/arnoldlu/p/11613842.html
Copyright © 2011-2022 走看看