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功能详解[转]》。

  • 相关阅读:
    李宏毅back propagation(lecturte7 )课堂笔记
    李宏毅deep learning(lecturte6)课堂笔记
    李宏毅classification+Logistic Regression(lecturte4+5)课堂笔记
    李宏毅Gradient Descent(lecturte3)课堂笔记
    02.get-post.php
    02.get-post
    01.php基础语法和JS区别.php
    11.子访问父
    10.父访问子--(children+refs)
    9.组件通讯(子传父)自定义事件
  • 原文地址:https://www.cnblogs.com/arnoldlu/p/11613842.html
Copyright © 2011-2022 走看看