fstab是什麼?被誰用?怎麼寫?

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功能詳解[轉]》。

聯繫方式:[email protected]

發佈了45 篇原創文章 · 獲贊 34 · 訪問量 47萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章