Linux文件系統(tǒng)基本概念記錄

真是一個(gè)無(wú)情的搬運(yùn)工

前言

本文同樣更新在私人公眾號(hào)上,在此推廣一下歡迎大家關(guān)注:

公眾號(hào)會(huì)定期更新一些計(jì)算機(jī)系統(tǒng)的底層知識(shí),爭(zhēng)取以最細(xì)節(jié)、最簡(jiǎn)潔的方式幫助讀者理解系統(tǒng)的一些知識(shí)。

image.png

inode

文件儲(chǔ)存在硬盤上,硬盤的最小存儲(chǔ)單位叫做"扇區(qū)"(Sector)。每個(gè)扇區(qū)儲(chǔ)存512字節(jié)(相當(dāng)于0.5KB)。

操作系統(tǒng)讀取硬盤的時(shí)候,不會(huì)一個(gè)個(gè)扇區(qū)地讀取,這樣效率太低,而是一次性連續(xù)讀取多個(gè)扇區(qū),即一次性讀取一個(gè)"塊"(block)。這種由多個(gè)扇區(qū)組成的"塊",是文件存取的最小單位。"塊"的大小,最常見(jiàn)的是4KB,即連續(xù)八個(gè) sector組成一個(gè) block。

  • inode內(nèi)容

inode包含文件的元信息,具體來(lái)說(shuō)有以下內(nèi)容:

* 文件的字節(jié)數(shù)

* 文件擁有者的User ID

* 文件的Group ID

* 文件的讀、寫、執(zhí)行權(quán)限

* 文件的時(shí)間戳,共有三個(gè):ctime指inode上一次變動(dòng)的時(shí)間,mtime指文件內(nèi)容上一次變動(dòng)的時(shí)間,atime指文件上一次打開(kāi)的時(shí)間。

* 鏈接數(shù),即有多少文件名指向這個(gè)inode

* 文件數(shù)據(jù)block的位置

  • inode大小

inode也會(huì)消耗硬盤空間,所以硬盤格式化的時(shí)候,操作系統(tǒng)自動(dòng)將硬盤分成兩個(gè)區(qū)域。一個(gè)是數(shù)據(jù)區(qū),存放文件數(shù)據(jù);另一個(gè)是inode區(qū)(inode table),存放inode所包含的信息。

每個(gè)inode節(jié)點(diǎn)的大小,一般是128字節(jié)或256字節(jié)。inode節(jié)點(diǎn)的總數(shù),在格式化時(shí)就給定,一般是每1KB或每2KB就設(shè)置一個(gè)inode。假定在一塊1GB的硬盤中,每個(gè)inode節(jié)點(diǎn)的大小為128字節(jié),每1KB就設(shè)置一個(gè)inode,那么inode table的大小就會(huì)達(dá)到128MB,占整塊硬盤的12.8%。

讀取文件的過(guò)程

  • 首先,系統(tǒng)找到這個(gè)文件名對(duì)應(yīng)的inode號(hào)碼;
  • 其次,通過(guò)inode號(hào)碼,獲取inode信息;
  • 最后,根據(jù)inode信息,找到文件數(shù)據(jù)所在的block,讀出數(shù)據(jù)。

硬鏈接

一般情況下,文件名和inode號(hào)碼是"一一對(duì)應(yīng)"關(guān)系,每個(gè)inode號(hào)碼對(duì)應(yīng)一個(gè)文件名。但是,Unix/Linux系統(tǒng)允許,多個(gè)文件名指向同一個(gè)inode號(hào)碼。

這意味著,可以用不同的文件名訪問(wèn)同樣的內(nèi)容;對(duì)文件內(nèi)容進(jìn)行修改,會(huì)影響到所有文件名;但是,刪除一個(gè)文件名,不影響另一個(gè)文件名的訪問(wèn)。這種情況就被稱為"硬鏈接"(hard link)。

ln命令可以創(chuàng)建硬鏈接: ln 源文件 目標(biāo)文件

軟鏈接

文件A和文件B的inode號(hào)碼雖然不一樣,但是文件A的內(nèi)容是文件B的路徑。讀取文件A時(shí),系統(tǒng)會(huì)自動(dòng)將訪問(wèn)者導(dǎo)向文件B。因此,無(wú)論打開(kāi)哪一個(gè)文件,最終讀取的都是文件B。這時(shí),文件A就稱為文件B的"軟鏈接"(soft link)或者"符號(hào)鏈接(symbolic link)。

這意味著,文件A依賴于文件B而存在,如果刪除了文件B,打開(kāi)文件A就會(huì)報(bào)錯(cuò):"No such file or directory"。這是軟鏈接與硬鏈接最大的不同:文件A指向文件B的文件名,而不是文件B的inode號(hào)碼,文件B的inode"鏈接數(shù)"不會(huì)因此發(fā)生變化。

一個(gè)數(shù)據(jù)塊大小4KB,則一個(gè)位圖塊可以表示410248個(gè)數(shù)據(jù)塊的使用情況,所以一個(gè)塊組中可存儲(chǔ)數(shù)據(jù)的大小是128MB(4 * 1024 * 8 * 4KB)

EXT-x文件系統(tǒng)中數(shù)據(jù)塊映射

Ext2/Ext3中數(shù)據(jù)塊映射方式:


image.png
image.png

于是inode
1024+ 1024^2 +1024^3+12=1,074,791,436

Extent學(xué)習(xí)記錄

Ext4中用extent樹(shù)代替了邏輯塊映射。使用extents,用一個(gè)struct ext4_extent結(jié)構(gòu)就可以映射多個(gè)數(shù)據(jù)塊,減少元數(shù)據(jù)塊的使用。

extent結(jié)構(gòu)是12個(gè)字節(jié),所以你可以在每個(gè)inode中最多試用5個(gè)extent。然后,前12個(gè)字節(jié)是extent區(qū)(40到51字節(jié)),被一個(gè)extent頭結(jié)構(gòu)占用,所以一個(gè)inode中實(shí)際上可以包含4個(gè)extent。

每個(gè)extent結(jié)構(gòu)中只有16個(gè)bit用來(lái)保存塊號(hào),實(shí)際上,最高位被保存了下來(lái)(最高位用來(lái)表示這個(gè)externt是“保存?預(yù)分?”還是已經(jīng)初始化, 部分用于EXT4的預(yù)分配功能)。這意味著,一個(gè)extent最大只能包含2的15次方個(gè)塊,當(dāng)一個(gè)block為4k大小的時(shí)候,即128MB。

128MB看起來(lái)足夠大了,但是當(dāng)你的文件大于0.5G的時(shí)候,這個(gè)文件就需要大于4個(gè)extent來(lái)保存整個(gè)block的索引。或者,當(dāng)你的文件很小,但是由很多不連續(xù)的片段組成。這些情況下,就需要用大于4個(gè)extent來(lái)組織文件。

Extent并沒(méi)有非常詳細(xì)的了解,后期有需要補(bǔ)充

Ext4中目錄項(xiàng)

Ext4文件系統(tǒng)中,一個(gè)目錄差不多是一個(gè)平面文件,映射任意長(zhǎng)度的字符串到文件系統(tǒng)中的一個(gè)inode。文件系統(tǒng)中存在多個(gè)目錄項(xiàng)引用同一個(gè)inode——硬鏈接,這也是硬鏈接不能鏈接其他文件系統(tǒng)中的文件的原因。

在目錄中并沒(méi)有存儲(chǔ)文件的數(shù)據(jù)信息,而只是存儲(chǔ)了一個(gè)類似C語(yǔ)言指針的東東,這個(gè)東東就是文件的inode id。而目錄中的子目錄數(shù)據(jù)和文件數(shù)據(jù)仍然是平鋪在磁盤上的。這樣,在目錄中通過(guò)這個(gè)指針就可以輕易的找到文件的數(shù)據(jù),而且目錄的數(shù)據(jù)和文件的數(shù)據(jù)組織也變得非常簡(jiǎn)單。

image.png

目錄本質(zhì)上也是一個(gè)文件,只不過(guò)其中存儲(chǔ)的數(shù)據(jù)是關(guān)于子目錄和文件的名稱信息

那么這個(gè)大數(shù)組中的元素是什么呢?就是圖6所示的這個(gè)結(jié)構(gòu)體。從該結(jié)構(gòu)體可以看出,每一項(xiàng)內(nèi)容包括inode的id、該結(jié)構(gòu)體的大小、文件(子目錄)名大小和文件名等信息。在檢索目錄內(nèi)容的時(shí)候,其實(shí)就是根據(jù)文件名獲得inode的id,然后在根據(jù)該id從inode表中獲得inode(文件)的詳細(xì)信息。

image.png

目錄查詢加速

在Ext4文件系統(tǒng)中這個(gè)索引是通過(guò)一個(gè)成為哈希樹(shù)(多叉樹(shù))的方式實(shí)現(xiàn)的,其中Key為文件名的哈希值,而Value則是具體的數(shù)據(jù)位置(磁盤塊位置)。由于Key是有序的,因此查找非常方便,也就是可以通過(guò)文件名快速的找到ext4_dir_entry_2,然后可以找到inode信息。

image.png
image.png

超級(jí)塊

在Linux操作系統(tǒng)的文件系統(tǒng)中,超級(jí)塊相當(dāng)于文件系統(tǒng)的地圖。在超級(jí)塊中保存著文件系統(tǒng)的屬性信息、磁盤布局和資源使用情況等信息。文件系統(tǒng)通過(guò)超級(jí)塊了解磁盤的布局,查找已用和可用資源等。超級(jí)塊又相當(dāng)于入口,文件系統(tǒng)的操作通常從超級(jí)塊開(kāi)始

struct super_block {  
746         struct list_head        s_list;         /* Keep this first */  
747         kdev_t                  s_dev;  
748         unsigned long           s_blocksize;  
749         unsigned char           s_blocksize_bits;  
750         unsigned char           s_dirt;  
751         unsigned long long      s_maxbytes;     /* Max file size */  
752         struct file_system_type *s_type;  
753         struct super_operations *s_op;  
754         struct dquot_operations *dq_op;  
755         struct quotactl_ops     *s_qcop;  
756         unsigned long           s_flags;  
757         unsigned long           s_magic;  
758         struct dentry           *s_root;  
759         struct rw_semaphore     s_umount;  
760         struct semaphore        s_lock;  
761         int                     s_count;  
762         atomic_t                s_active;  
763   
764         struct list_head        s_dirty;        /* dirty inodes */  
765         struct list_head        s_locked_inodes;/* inodes being synced */  
766         struct list_head        s_files;  
767   
768         struct block_device     *s_bdev;  
769         struct list_head        s_instances;  
770         struct quota_info       s_dquot;        /* Diskquota specific options */  
771   
772         union {  
773                 struct minix_sb_info    minix_sb;  
774                 struct ext2_sb_info     ext2_sb;  
775                 struct ext3_sb_info     ext3_sb;  
776                 struct hpfs_sb_info     hpfs_sb;  
777                 struct ntfs_sb_info     ntfs_sb;  
778                 struct msdos_sb_info    msdos_sb;  
779                 struct isofs_sb_info    isofs_sb;  
780                 struct nfs_sb_info      nfs_sb;  
781                 struct sysv_sb_info     sysv_sb;  
782                 struct affs_sb_info     affs_sb;  
783                 struct ufs_sb_info      ufs_sb;  
784                 struct efs_sb_info      efs_sb;  
785                 struct shmem_sb_info    shmem_sb;  
786                 struct romfs_sb_info    romfs_sb;  
787                 struct smb_sb_info      smbfs_sb;  
788                 struct hfs_sb_info      hfs_sb;  
789                 struct adfs_sb_info     adfs_sb;  
790                 struct qnx4_sb_info     qnx4_sb;  
791                 struct reiserfs_sb_info reiserfs_sb;  
792                 struct bfs_sb_info      bfs_sb;  
793                 struct udf_sb_info      udf_sb;  
794                 struct ncp_sb_info      ncpfs_sb;  
795                 struct usbdev_sb_info   usbdevfs_sb;  
796                 struct jffs2_sb_info    jffs2_sb;  
797                 struct cramfs_sb_info   cramfs_sb;  
798                 void                    *generic_sbp;  
799         } u;  
800         /* 
801          * The next field is for VFS *only*. No filesystems have any business 
802          * even looking at it. You had been warned. 
803          */  
804         struct semaphore s_vfs_rename_sem;      /* Kludge */  
805   
806         /* The next field is used by knfsd when converting a (inode number based) 
807          * file handle into a dentry. As it builds a path in the dcache tree from 
808          * the bottom up, there may for a time be a subpath of dentrys which is not 
809          * connected to the main tree.  This semaphore ensure that there is only ever 
810          * one such free path per filesystem.  Note that unconnected files (or other 
811          * non-directories) are allowed, but not unconnected diretories. 
812          */  
813         struct semaphore s_nfsd_free_path_sem;  
814 }

s_list:指向超級(jí)塊鏈表的指針,這個(gè)struct list_head是很熟悉的結(jié)構(gòu)了,里面其實(shí)就是用于連接關(guān)系的prev和next字段。

內(nèi)核中的結(jié)構(gòu)處理都是有講究的(內(nèi)核協(xié)議棧中也說(shuō)過(guò)),內(nèi)核單獨(dú)使用一個(gè)簡(jiǎn)單的結(jié)構(gòu)體將所有的super_block都鏈接起來(lái),但是這個(gè)結(jié)構(gòu)不是super_block本身,因?yàn)楸旧頂?shù)據(jù)結(jié)構(gòu)太大,效率不高,所有僅僅使用

struct

{

list_head prev;

list_head next;

}

這樣的結(jié)構(gòu)來(lái)將super_block中的s_list鏈接起來(lái),那么遍歷到s_list之后,直接讀取super_block這么長(zhǎng)的一個(gè)內(nèi)存塊,就可以將這個(gè)

super_block直接讀進(jìn)來(lái)!這樣就很快捷方便!這也是為什么s_list必須放在第一個(gè)字段的原因。

s_dev:包含該具體文件系統(tǒng)的塊設(shè)備標(biāo)識(shí)符。例如,對(duì)于 /dev/hda1,其設(shè)備標(biāo)識(shí)符為 0x301

s_blocksize:文件系統(tǒng)中數(shù)據(jù)塊大小,以字節(jié)單位

s_blocksize_bits:上面的size大小占用位數(shù),例如512字節(jié)就是9 bits

s_dirt:臟位,標(biāo)識(shí)是否超級(jí)塊被修改

s_maxbytes:允許的最大的文件大小(字節(jié)數(shù))

struct file_system_type *s_type:文件系統(tǒng)類型(也就是當(dāng)前這個(gè)文件系統(tǒng)屬于哪個(gè)類型?ext2還是fat32)

要區(qū)分“文件系統(tǒng)”和“文件系統(tǒng)類型”不一樣!一個(gè)文件系統(tǒng)類型下可以包括很多文件系統(tǒng)即很多的super_block,后面會(huì)說(shuō)!

struct super_operations *s_op:指向某個(gè)特定的具體文件系統(tǒng)的用于超級(jí)塊操作的函數(shù)集合

struct dquot_operations *dq_op:指向某個(gè)特定的具體文件系統(tǒng)用于限額操作的函數(shù)集合

struct quotactl_ops *s_qcop:用于配置磁盤限額的的方法,處理來(lái)自用戶空間的請(qǐng)求
s_flags:安裝標(biāo)識(shí)

s_magic:區(qū)別于其他文件系統(tǒng)的標(biāo)識(shí)

s_root:指向該具體文件系統(tǒng)安裝目錄的目錄項(xiàng)

s_umount:對(duì)超級(jí)塊讀寫時(shí)進(jìn)行同步

s_lock:鎖標(biāo)志位,若置該位,則其它進(jìn)程不能對(duì)該超級(jí)塊操作

s_count:對(duì)超級(jí)塊的使用計(jì)數(shù)

s_active:引用計(jì)數(shù)

s_dirty:已修改的索引節(jié)點(diǎn)inode形成的鏈表,一個(gè)文件系統(tǒng)中有很多的inode,有些inode節(jié)點(diǎn)的內(nèi)容會(huì)被修改,那么會(huì)先被記錄,然后寫回磁盤。

s_locked_inodes:要進(jìn)行同步的索引節(jié)點(diǎn)形成的鏈表

s_files:所有的已經(jīng)打開(kāi)文件的鏈表,這個(gè)file和實(shí)實(shí)在在的進(jìn)程相關(guān)的

s_bdev:指向文件系統(tǒng)被安裝的塊設(shè)備

u:u 聯(lián)合體域包括屬于具體文件系統(tǒng)的超級(jí)塊信息

s_instances:具體的意義后來(lái)會(huì)說(shuō)的!(同一類型的文件系統(tǒng)通過(guò)這個(gè)子墩將所有的super_block連接起來(lái))

s_dquot:磁盤限額相關(guān)選項(xiàng)

文件系統(tǒng)中的各個(gè)數(shù)據(jù)結(jié)構(gòu)源碼:
https://www.cnblogs.com/linux-xin/p/8126999.html

參考鏈接

http://www.ruanyifeng.com/blog/2011/12/inode.html

https://www.cnblogs.com/alantu2018/p/8461272.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容