一,mount系統調用--相關代碼
源碼位置:kernel/fs/Namespace.c文件的do_mount()函數,函數
dev_name指的是要掛載文件系統的名字,如tmpfs,
dir_name指的是文件系統要被掛載的目標目錄
type_page指的是要掛載的文件系統的類型
flags指的是掛載選項,如MS_RDONLY等等
data_page指的是一些額外選項等,如wait關鍵字spa
1,do_mount()函數首先會作一些參數檢查,dir_name不能爲空而且大小不能超過一個PAGE大小,將data_page超過一個PAGE大小的部分截斷。.net
if(!memchr(dir_name,0,PAGE_SIZE))code
檢查data_page的長度是否超過一個page,若是超過,則將超出的部分截斷。對象
if (data_page)
((char *)data_page)[PAGE_SIZE - 1] = 0;blog
do_mount()函數首先調用kern_path()函數,將dir_name轉換爲struct path結構體,ip
2,而後根據不一樣的flag參數去設置不一樣的mnt_flags臨時變量,若是flag中沒有包含MS_REMOUNT,MS_BIND,MS_MOVE,MS_SHARED,MS_PRIVATE,等,那麼最後會調用
do_new_mount()函數。get
3,do_new_mount()函數 源碼
path參數是dir_name通過kern_path()轉換後的path結構體
type參數指的是文件系統的類型
flags參數指的是一些mount選項
mnt_flags參數指的是一些monut選項
name參數指的是要掛載文件系統的名字,如tmpfs
data參數指的是一些額外選項等,如wait關鍵字hash
do_new_mount()函數首先調用do_kern_mount(type,flags,name,data)函數,該函數的做用是創建一塊新的安裝塊區域,獲取一個vfsmount實例,獲取源文件系統vfsmount結構,並經過特定文件系統的操做裝載到系統系統中,返回裝載點的根目錄,而後調用do_add_mount(real_mount(mnt),path,mnt_flags)函數,該函數的做用是將mount實例掛載到mount樹上去,將源文件系統增長到目的文件系統中。
do_kern_mount()函數細節,do_kern_mount()首先調用get_fs_type()函數返回要掛載文件系統的file_system_type實例,file_system_type是在各個文件系統在系統啓動的時候 註冊進內核的,全部註冊的文件系統造成一個單鏈表,而後do_kern_mount()調用vfs_kern_mount()函數,vfs_kern_mount()函數的做用是分配一個struct mount結構體,而後vfs_kern_mount()調用各個文件系統file_system_type結構的mount成員函數(如ext4則會調用ext4_mount函數),該函數的做用是建立該文件系統的超級快對象,返回該文件系統的根目錄(root)的dentry實例,最後將建立的超級快對象賦值給新建立的vfsmount結構所指的超級快,同時vfsmount所指的mnt_root點賦值爲超級快所指的根dentry.
do_add_mount()函數細節,該函數做用是將當前mount實例加到mount樹上,do_add_mount()函數的兩個關鍵點,lock_mount()函數和graft_tree()函數,lock_mount()檢查若是當前要掛載的目錄以前已經掛載其它文件系統,則要進行文件系統切換動做,graft是嫁接的意思,是將將要mount的目錄樹與當前目錄的文件系統的目錄樹鏈接起來,很像嫁接技術,而原來文件系統的目錄樹沒損傷。
lock_mount()函數主要調用lookup_mnt()函數,該函數返回一個struct vfsmount的實例,lookup_mnt()函數調用__lookup_mnt()函數返回一個struct mount的實例,在同個父文件系統下的同個目錄能夠做爲多個子文件系統的掛載點,因此若是真的掛載了多個子文件系統,那麼這幾個子文件系統經過散列函數確定會被放在哈希表裏的同一條鏈表上。__lookup_mnt()函數就是返回該目錄下最後掛載的文件系統mount的實例。__lookup_mnt()函數以下所示:
graft_tree()函數的實現細節,graft_tree()函數主要調用attach_recursive_mnt()函數,static int attach_recursive_mnt(struct mount*source_mnt,struct path*path,struct path*parent_path),attach_recursive_mnt()函數作的主要操做是1.經過mnt_set_mountpoint()將子vfsmount中的mnt_parent指向父vfsmount,將子vfsmount的mnt_mountpoint指向位於父文件系統中的掛載點dentry;2.經過commit_tree()將子文件系統添加到內核的文件系統哈希表中,並將子文件系統添加到父文件系統對應的子文件系統鏈表中; commit_tree()函數的做用是1.將當前文件系統的名字空間設置爲父名字空間,父vfsmount經過當前vfsmount中的mnt_parent獲取;再將其鏈接到父名字空間鏈表中。2.將當前vfsmount加入到對應哈希值的衝突鏈表當中,哈希值經過hash()計算。其中,mnt_hash做爲鏈表元素。3.將當前vfsmount加入到父vfsmount對應的子文件系統鏈mnt_mounts中。其中,mnt_child做爲鏈表元素。