關鍵詞:fstab、mount -a、fsck等等。html
fstab是file system table的意思,即文件系統表。linux
它在開機的時候告訴系統掛載哪些分區、掛載點是什麼、以什麼格式掛載、掛載的選項等等。c++
而後系統在開機的時候就根據fstab內容,執行掛載操做。在掛載完以後,就能夠在文件系統上進行操做。shell
將須要掛載的分區放入fstab以後,就不須要手動掛載。app
init進程在啓動的時候會解析/etc/inittab文件,並執行其中選項。async
# /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配置執行相應關在操做。ide
參考文檔:《busybox啓動流程簡單解析:從init到shell login》。函數
fstab是被mount命令解析,而後根據解析內容執行操做。oop
mount命令將fstab中配置解析成一個struct mntent實例:post
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()進行掛載。
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級別檢驗完成以後進行檢驗 |
fstab被mount -a命令解析,而後針對不一樣文件系統類型將設備掛載到指定目錄。
若是須要將某一個設備在開機是掛在到系統中,須要經過編寫fstab便可,共6列須要配置。
修改fstab以後,經過mount -a當即生效,或者經過重啓生效。
參考文檔:《A complete fstab guide》、《Linux命令-自動掛載文件/etc/fstab功能詳解[轉]》。