大家好,我們今天繼續來學習Linux系統部分。上一次我們學習了內存級的文件,下面我們來學習磁盤級的文件。那么話不多說,我們開始今天的學習:
目錄
Ext系列?件系統
1. 理解硬件
1-1 磁盤、服務器、機柜、機房
1-2 磁盤物理結構
1-3 磁盤的存儲結構
1-4 磁盤的邏輯結構
1-4-1 理解過程
1-4-2 真實過程
1-5 CHS && LBA地址
2. 引??件系統
2-1 引?"塊"概念
2-2 引?"分區"概念
2-3 引?"inode"概念
3. ext2 ?件系統
3-1 宏觀認識
3-2 Block Group
3-3 塊組內部構成
3-3-1 超級塊(Super Block)
3-3-2 GDT(Group Descriptor Table)
3-3-3 塊位圖(Block Bitmap)
3-3-4 inode位圖(Inode Bitmap)
3-3-5 i節點表(Inode Table)
3-3-6 Data Block
3-4 inode和datablock映射
3-5 ?錄與?件名
3-6 路徑解析
3-7 路徑緩存
3-8 掛載分區
3-9 ?件系統總結
4. 軟硬連接
4-1 硬鏈接
4-2 軟鏈接
4-3 軟硬連接對?
4-4 軟硬連接的?途
Ext系列?件系統
1. 理解硬件
我們想要訪問文件,需要通過基礎I/O來把磁盤中的文件加載到內存中。所以被打開的文件存儲在內存中,沒有被打開的文件存儲在磁盤中。那么我們該如何從磁盤上找到我們想要的文件呢?不著急,我們先來認識一下磁盤:
1-1 磁盤、服務器、機柜、機房
機械磁盤是計算機中唯?的?個機械設備磁盤--- 外設特點:慢容量?,價格便宜
這兩張圖是磁盤的結構,
將一組磁盤整合到一起,就是一個服務器,
將服務器再整合到一起,就是一個機柜,
機柜再整合到一起就是一個機房,這一整套系統都是用來進行存儲的。磁盤有許多種,每種磁盤的存儲方式也有不同,機械磁盤通過磁存儲,其工作原理完全圍繞磁鐵和磁場展開;固態硬盤通過電荷的保存與讀取來記錄數據,下面我們以機械磁盤舉例來學習:
1-2 磁盤物理結構
磁盤通過盤片的轉動和磁頭的擺動來將數據存儲到磁盤的不同位置
1-3 磁盤的存儲結構
磁盤并不是一個單層的結構,一個磁盤通常由多個盤片和磁頭組成,每個盤片的正反面都可以進行存儲,每個面對應一個磁頭,比如說三張盤片就要對應六個磁頭。但需要注意的是,這些磁頭都由一個機械臂控制,因此所有磁頭的運動軌跡是相同的。
我們將盤片分為多個同心圓,每一個同心圓都是一個磁道,每一個磁道又被分為多個扇區,扇區就是磁盤進行存儲的最小單位。所有面的相同磁道被稱為柱面。
所以在定位一個扇區時,磁頭先擺動到該柱面位置,再確定該扇區對應哪一個磁頭,隨后盤片轉動再定位該扇區,這樣的定位方式叫做CHS地址定位
1. 扇區是從磁盤讀出和寫?信息的最?單位,通常??為 512 字節。2. 磁頭(head)數:每個盤??般有上下兩?,分別對應1個磁頭,共2個磁頭3. 磁道(track)數:磁道是從盤?外圈往內圈編號0磁道,1磁道...,靠近主軸的同?圓?于停靠磁頭,不存儲數據4. 柱?(cylinder)數:磁道構成柱?,數量上等同于磁道個數5. 扇區(sector)數:每個磁道都被切分成很多扇形區域,每道的扇區數量相同6. 圓盤(platter)數:就是盤?的數量7. 磁盤容量=磁頭數 × 磁道(柱?)數 × 每道扇區數 × 每扇區字節數
CHS尋址對早期的磁盤?常有效,知道?哪個磁頭,讀取哪個柱?上的第?扇區就可以讀到數據了。但是CHS模式?持的硬盤容量有限,因為系統?8bit來存儲磁頭地址,?10bit來存儲柱?地址,?6bit來存儲扇區地址,??個扇區共有512Byte,這樣使?CHS尋址?塊硬盤最?容量為256 * 1024 * 63 * 512B = 8064 MB(1MB = 1048576B)(若按1MB=1000000B來算就是8.4GB)
1-4 磁盤的邏輯結構
為此,要找到一種更為方便的尋址方式,難道磁盤只有光盤這樣一種形式的嗎?
1-4-1 理解過程
這是磁帶,通常來存儲音樂,把磁帶拆開來看,把磁帶拉直,它的結構是長條的。也就是說,我們可以認為磁帶的存儲是線性結構

這樣我們可以為每?個扇區提供?個線性地址(其實就是數組下標),這種地址叫做LBA
1-4-2 真實過程
所以,磁盤的真實情況是:磁道:某?盤?的某?個磁道展開:
柱?:整個磁盤所有盤?的同?個磁道,即柱?展開:
整盤:
我們將其全轉換成一維數組:
現在我們為每一個扇區都提供一個下標,我們叫做LBA(Logical Block Address)地址,其實就是線性地址。所以怎么計算得到這個LBA地址呢?
1-5 CHS && LBA地址
CHS轉成LBA:1. 磁頭數*每磁道扇區數 = 單個柱?的扇區總數2. LBA = 柱?號C*單個柱?的扇區總數 + 磁頭號H*每磁道扇區數 + 扇區號S - 13. 即:LBA = 柱?號C*(磁頭數*每磁道扇區數) + 磁頭號H*每磁道扇區數 + 扇區號S - 14. 扇區號通常是從1開始的,?在LBA中,地址是從0開始的5. 柱?和磁道都是從0開始編號的6. 總柱?,磁道個數,扇區總數等信息,在磁盤內部會?動維護,上層開機的時候,會獲取到這些參數。
LBA轉成CHS:1. 柱?號C = LBA // (磁頭數*每磁道扇區數)【就是單個柱?的扇區總數】2. 磁頭號H = (LBA % (磁頭數*每磁道扇區數)) // 每磁道扇區數3. 扇區號S = (LBA % 每磁道扇區數) + 14. "//": 表?除取整
從此往后,在磁盤使?者看來,根本就不關?CHS地址,?是直接使?LBA地址,磁盤內部??轉換。所以:從現在開始,磁盤就是?個 元素為扇區 的?維數組,數組的下標就是每?個扇區的LBA地址。OS使?磁盤,就可以??個數字訪問磁盤扇區了。
2. 引??件系統
2-1 引?"塊"概念
其實硬盤是典型的“塊”設備,操作系統讀取硬盤數據的時候,其實是不會?個個扇區地讀取,這樣效率太低,?是?次性連續讀取多個扇區,即?次性讀取?個”塊”(block)。硬盤的每個分區是被劃分為?個個的”塊”。?個”塊”的??是由格式化的時候確定的,并且不可以更改,最常?的是4KB,即連續?個扇區組成?個 ”塊”。”塊”是?件存取的最?單位。
注意:磁盤就是?個三維數組,我們把它看待成為?個"?維數組",數組下標就是LBA,每個元素都是扇區每個扇區都有LBA,那么8個扇區?個塊,每?個塊的地址我們也能算出來。知道LBA:塊號 = LBA/8知道塊號:LAB=塊號*8 + n. (n是塊內第?個扇區)
2-2 引?"分區"概念
其實磁盤是可以被分成多個分區(partition)的,以Windows觀點來看,你可能會有?塊磁盤并且將它分區成C,D,E盤。那個C,D,E就是分區。分區從實質上說就是對硬盤的?種格式化。但是Linux的設備都是以?件形式存在,那是怎么分區的呢?柱?是分區的最?單位,我們可以利?參考柱?號碼的?式來進?分區,其本質就是設置每個區的起始柱?和結束柱?號碼。 此時我們可以將硬盤上的柱?(分區)進?平鋪,將其想象成?個?的平?,如下圖所?:
2-3 引?"inode"概念
之前我們說過 ?件=數據+屬性 ,我們使? ls -l 的時候看到的除了看到?件名,還能看到?件元數據(屬性)。
[root@localhost linux]# ls -l
總?量 12
-rwxr-xr-x. 1 root root 7438 "9? 13 14:56" a.out
-rw-r--r--. 1 root root 654 "9? 13 14:56" test.c
每?包含7列:模式硬鏈接數?件所有者組??最后修改時間?件名ls -l讀取存儲在磁盤上的?件信息,然后顯?出來
[root@localhost linux]# stat test.c
File: "test.c"
Size: 654 Blocks: 8 IO Block: 4096 普通?件
Device: 802h/2050d Inode: 263715 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2017-09-13 14:56:57.059012947 +0800
Modify: 2017-09-13 14:56:40.067012944 +0800
Change: 2017-09-13 14:56:40.069012948 +0800
到這我們要思考?個問題,?件數據都儲存在”塊”中,那么很顯然,我們還必須找到?個地?儲存?件的元信息(屬性信息),?如?件的創建者、?件的創建?期、?件的??等等。這種儲存?件元信息的區域就叫做inode,中?譯名為”索引節點”。
文件的內容和屬性是分開存儲的,每?個?件都有對應的inode,??包含了與該?件有關的?些信息。為了能解釋清楚inode,我們需要是深?了解?下?件系統。
所以?個?件的屬性inode?什么樣?呢?
/*
* Structure of an inode on the disk
*/
struct ext2_inode {__le16 i_mode; /* File mode */__le16 i_uid; /* Low 16 bits of Owner Uid */__le32 i_size; /* Size in bytes */__le32 i_atime; /* Access time */__le32 i_ctime; /* Creation time */__le32 i_mtime; /* Modification time */__le32 i_dtime; /* Deletion Time */__le16 i_gid; /* Low 16 bits of Group Id */__le16 i_links_count; /* Links count */__le32 i_blocks; /* Blocks count */__le32 i_flags; /* File flags */union {struct {__le32 l_i_reserved1;} linux1;struct {__le32 h_i_translator;} hurd1;struct {__le32 m_i_reserved1;} masix1;} osd1; /* OS dependent 1 */__le32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */__le32 i_generation; /* File version (for NFS) */__le32 i_file_acl; /* File ACL */__le32 i_dir_acl; /* Directory ACL */__le32 i_faddr; /* Fragment address */union {struct {__u8 l_i_frag; /* Fragment number */__u8 l_i_fsize; /* Fragment size */__u16 i_pad1;__le16 l_i_uid_high; /* these 2 fields */__le16 l_i_gid_high; /* were reserved2[0] */__u32 l_i_reserved2;} linux2;struct {__u8 h_i_frag; /* Fragment number */__u8 h_i_fsize; /* Fragment size */__le16 h_i_mode_high;__le16 h_i_uid_high;__le16 h_i_gid_high;__le32 h_i_author;} hurd2;struct {__u8 m_i_frag; /* Fragment number */__u8 m_i_fsize; /* Fragment size */__u16 m_pad1;__u32 m_i_reserved2[2];} masix2;} osd2; /* OS dependent 2 */
};
/*
* Constants relative to the data blocks
*/
#define EXT2_NDIR_BLOCKS 12
#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
?件名屬性并未納?到inode數據結構內部inode的???般是128字節或者256,我們后?統?128字節任何?件的內容??可以不同,由于屬性存儲在結構體變量中,所以屬性???定是相同的
簡單介紹了分區結構,下面我們來具體認識一下文件系統
3. ext2 ?件系統
3-1 宏觀認識
我們想要在硬盤上儲?件,必須先把硬盤格式化為某種格式的?件系統,才能存儲?件。?件系統的?的就是組織和管理硬盤中的?件。在Linux 系統中,最常?的是 ext2 系列的?件系統。其早期版本為 ext2,后來?發展出 ext3 和 ext4。ext3 和 ext4 雖然對 ext2 進?了增強,但是其核?設計并沒有發?變化,我們仍是以較?的 ext2 作為演?對象。ext2?件系統將整個分區劃分成若?個同樣??的塊組 (Block Group),如下圖所?。只要能管理?個分區就能管理所有分區,也就能管理所有磁盤?件。
上圖中啟動塊(Boot Block/Sector)的??是確定的,為1KB,由PC標準規定,?來存儲磁盤分區信息和啟動信息,任何?件系統都不能修改啟動塊。啟動塊之后才是ext2?件系統的開始。
由圖可見,文件系統是以分區為載體的,一塊磁盤被分為不同的區,每個區都是一個文件系統,每個文件系統又被分為多個組,在每個組內部的空間,又有著不同的功能,下面我們來介紹一下:
3-2 Block Group
ext2?件系統會根據分區的??劃分為數個Block Group。?每個Block Group都有著相同的結構組成。
3-3 塊組內部構成
3-3-1 超級塊(Super Block)
存放?件系統本?的結構信息,描述整個分區的?件系統信息。記錄的信息主要有:bolck 和 inode的總量,未使?的block和inode的數量,?個block和inode的??,最近?次掛載的時間,最近?次寫?數據的時間,最近?次檢驗磁盤的時間等其他?件系統的相關信息。Super Block的信息被破壞,可以說整個?件系統結構就被破壞了
超級塊在每個塊組的開頭都有?份拷?(第?個塊組必須有,后?的塊組可以沒有)。 為了保證?件系統在磁盤部分扇區出現物理問題的情況下還能正常?作,就必須保證?件系統的super block信息在這種情況下也能正常訪問。所以?個?件系統的super block會在多個block group中進?備份,這些super block區域的數據保持?致。
struct ext2_super_block {__le32 s_inodes_count; /* Inodes count */__le32 s_blocks_count; /* Blocks count */__le32 s_r_blocks_count; /* Reserved blocks count */__le32 s_free_blocks_count; /* Free blocks count */__le32 s_free_inodes_count; /* Free inodes count */__le32 s_first_data_block; /* First Data Block */__le32 s_log_block_size; /* Block size */__le32 s_log_frag_size; /* Fragment size */__le32 s_blocks_per_group; /* # Blocks per group */__le32 s_frags_per_group; /* # Fragments per group */__le32 s_inodes_per_group; /* # Inodes per group */__le32 s_mtime; /* Mount time */__le32 s_wtime; /* Write time */__le16 s_mnt_count; /* Mount count */__le16 s_max_mnt_count; /* Maximal mount count */__le16 s_magic; /* Magic signature */__le16 s_state; /* File system state */__le16 s_errors; /* Behaviour when detecting errors */__le16 s_minor_rev_level; /* minor revision level */__le32 s_lastcheck; /* time of last check */__le32 s_checkinterval; /* max. time between checks */__le32 s_creator_os; /* OS */__le32 s_rev_level; /* Revision level */__le16 s_def_resuid; /* Default uid for reserved blocks */__le16 s_def_resgid;__le32 s_first_ino; /* First non-reserved inode */__le16 s_inode_size; /* size of inode structure */__le16 s_block_group_nr; /* block group # of this superblock */__le32 s_feature_compat; /* compatible feature set */__le32 s_feature_incompat; /* incompatible feature set */__le32 s_feature_ro_compat; /* readonly-compatible feature set */__u8 s_uuid[16]; /* 128-bit uuid for volume */char s_volume_name[16]; /* volume name */char s_last_mounted[64]; /* directory where last mounted */__le32 s_algorithm_usage_bitmap; /* For compression */__u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/__u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */__u16 s_padding1;__u8 s_journal_uuid[16]; /* uuid of journal superblock */__u32 s_journal_inum; /* inode number of journal file */__u32 s_journal_dev; /* device number of journal file */__u32 s_last_orphan; /* start of list of inodes to delete */__u32 s_hash_seed[4]; /* HTREE hash seed */__u8 s_def_hash_version; /* Default hash version to use */__u8 s_reserved_char_pad;__u16 s_reserved_word_pad;__le32 s_default_mount_opts;__le32 s_first_meta_bg; /* First metablock block group */__u32 s_reserved[190]; /* Padding to the end of the block */
};
3-3-2 GDT(Group Descriptor Table)
塊組描述符表,描述塊組屬性信息,整個分區分成多個塊組就對應有多少個塊組描述符。每個塊組描述符存儲?個塊組 的描述信息,如在這個塊組中從哪?開始是inode Table,從哪?開始是Data Blocks,空閑的inode和數據塊還有多少個等等。塊組描述符在每個塊組的開頭都有?份拷?。
struct ext2_group_desc
{__le32 bg_block_bitmap; /* Blocks bitmap block */__le32 bg_inode_bitmap; /* Inodes bitmap */__le32 bg_inode_table; /* Inodes table block*/__le16 bg_free_blocks_count; /* Free blocks count */__le16 bg_free_inodes_count; /* Free inodes count */__le16 bg_used_dirs_count; /* Directories count */__le16 bg_pad;__le32 bg_reserved[3];
};
3-3-3 塊位圖(Block Bitmap)
Block Bitmap中記錄著Data Block中哪個數據塊已經被占?,哪個數據塊沒有被占?
3-3-4 inode位圖(Inode Bitmap)
每個bit表??個inode是否空閑可?。
3-3-5 i節點表(Inode Table)
存放?件屬性 如 ?件??,所有者,最近修改時間等當前分組所有Inode屬性的集合inode編號以分區為單位,整體劃分,不可跨分區
3-3-6 Data Block
數據區:存放?件內容,也就是?個?個的Block。根據不同的?件類型有以下?種情況:對于普通?件,?件的數據存儲在數據塊中。對于?錄,該?錄下的所有?件名和?錄名存儲在所在?錄的數據塊中,除了?件名外,ls -l命令看到的其它信息保存在該?件的inode中。Block 號按照分區劃分,不可跨分區
3-4 inode和datablock映射
inode內部存在 __le32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ , EXT2_N_BLOCKS =15,就是?來進?inode和block映射的
索引塊是用來記錄文件實際占用的字節數,一個一級索引塊可以存儲1024個直接塊的指針,讓用戶和系統能夠了解文件的規模
inode 和數據塊,跨組編號的,inode 和數據塊,不能跨分區。所以,在同一個分區內部,inode 編號,和塊號都是唯一的,在不同的分區內,可以使用相同的inode編號。
我們使用文件的inode編號就能找到這個文件的所有內容和屬性數據
3-5 ?錄與?件名
那么話又說回來了,為什么文件名不被存儲在inode中呢?
因為在Linux中,目錄也被視作是文件,所以目錄的存儲也是按照如上方式進行的,對于目錄來說,內容保存的是:?件名和Inode號的映射關系,所以若目錄中有重名文件時,這種映射就會產生沖突,導致無法準確找到文件對應的 inode,進而無法獲取文件的信息和實際數據。
訪問?件,必須打開當前?錄,根據?件名,獲得對應的inode號,然后進??件訪問訪問?件必須要知道當前?作?錄,本質是必須能打開當前?作?錄?件,查看?錄?件的內容!
3-6 路徑解析
我們訪問文件的時候,誰來給我們提供路徑呢?
我們需要通過進程來訪問文件,所以由進程來提供路徑
問題:打開當前?作?錄?件,查看當前?作?錄?件的內容?當前?作?錄不也是?件嗎?我們訪問當前?作?錄不也是只知道當前?作?錄的?件名嗎?要訪問它,不也得知道當前?作?錄的inode嗎?答案1:所以也要打開:當前?作?錄的上級?錄,額....,上級?錄不也是?錄嗎??不還是上?的問題嗎?答案2:所以類似"遞歸",需要把路徑中所有的?錄全部解析,出?是"/"根?錄。最終答案3:?實際上,任何?件,都有路徑,訪問?標?件,?如:/home/user/code/test/test/test.c都要從根?錄開始,依次打開每?個?錄,根據?錄名,依次訪問每個?錄下指定的?錄,直到訪問到test.c。這個過程叫做Linux路徑解析。
所以,我們知道了:訪問?件必須要有?錄+?件名=路徑的原因根?錄固定?件名,inode號,?需查找,系統開機之后就必須知道
3-7 路徑緩存
問題1:Linux磁盤中,存在真正的?錄嗎?答案:不存在,只有?件。只保存?件屬性+?件內容問題2:訪問任何?件,都要從/?錄開始進?路徑解析?答案:原則上是,但是這樣太慢,所以Linux會緩存歷史路徑結構問題2:Linux?錄的概念,怎么產?的?答案:打開的?件是?錄的話,由OS??在內存中進?路徑維護
struct dentry {atomic_t d_count;unsigned int d_flags; /* protected by d_lock */spinlock_t d_lock; /* per dentry lock */struct inode *d_inode; /* Where the name belongs to - NULL is* negative *//** The next three fields are touched by __d_lookup. Place them here* so they all fit in a cache line.*/struct hlist_node d_hash; /* lookup hash list */struct dentry *d_parent; /* parent directory */struct qstr d_name;struct list_head d_lru; /* LRU list *//** d_child and d_rcu can share memory*/union {struct list_head d_child; /* child of parent list */struct rcu_head d_rcu;} d_u;struct list_head d_subdirs; /* our children */struct list_head d_alias; /* inode alias list */unsigned long d_time; /* used by d_revalidate */struct dentry_operations *d_op;struct super_block *d_sb; /* The root of the dentry tree */void *d_fsdata; /* fs-specific data */
#ifdef CONFIG_PROFILINGstruct dcookie_struct *d_cookie; /* cookie, if any */
#endifint d_mounted;unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */
};
1. 每個?件其實都要有對應的dentry結構,包括普通?件。這樣所有被打開的?件,就可以在內存中形成整個樹形結構2. 整個樹形節點也同時會?屬于LRU(Least Recently Used,最近最少使?)結構中,進?節點淘汰3. 整個樹形節點也同時會?屬于Hash,?便快速查找4. 更重要的是,這個樹形結構,整體構成了Linux的路徑緩存結構,打開訪問任何?件,都在先在這棵樹下根據路徑進?查找,找到就返回屬性inode和內容,沒找到就從磁盤加載路徑,添加dentry結構,緩存新路徑
3-8 掛載分區
我們已經能夠根據inode號在指定分區找?件了,也已經能根據?錄?件內容,找指定的inode了,在指定的分區內,我們可以為所欲為了。可是:問題:inode不是不能跨分區嗎?Linux不是可以有多個分區嗎?我怎么知道我在哪?個分區???
分區寫??件系統,?法直接使?,需要和指定的?錄關聯,進?掛載才能使?。所以,可以根據訪問?標?件的"路徑前綴"準確判斷我在哪?個分區。
3-9 ?件系統總結
4. 軟硬連接
4-1 硬鏈接
我們看到,真正找到磁盤上?件的并不是?件名,?是inode。其實在linux中可以讓多個?件名對應于同?個inode。
[root@localhost linux]# touch abc
[root@localhost linux]# ln abc def
[root@localhost linux]# ls -li abc def
263466 abc
263466 def
abc和def的鏈接狀態完全相同,他們被稱為指向?件的硬鏈接。內核記錄了這個連接數,inode263466 的硬連接數為2。我們在刪除?件時?了兩件事情:1.在?錄中將對應的記錄刪除,2.將硬連接數-1,如果為0,則將對應的磁盤釋放。
硬鏈接不是一個獨立的文件,因為它沒有獨立的inode,硬鏈接本質上是多一個文件名指向對應的目標文件,很像c++中的引用,所以硬鏈接可以用來做文件備份。
4-2 軟鏈接
硬鏈接是通過inode引?另外?個?件,軟鏈接是通過名字引?另外?個?件,但實際上,新的?件和被引?的?件的inode不同,應?常?上可以想象成?個快捷?式。
[root@localhost linux]# ln -s abc.s abc
[root@localhost linux]# ls -li
263563 -rw-r--r--. 2 root root 0 9? 15 17:45 abc
261678 lrwxrwxrwx. 1 root root 3 9? 15 17:53 abc.s -> abc
263563 -rw-r--r--. 2 root root 0 9? 15 17:45 def
用一張圖來表示軟硬連接就是:
4-3 軟硬連接對?
軟連接是獨??件硬連接不是獨立文件只是?件名和?標?件inode的映射關系
4-4 軟硬連接的?途
硬鏈接1. 目錄中的.和.. 就是硬鏈接2. ?件備份軟連接1. 類似快捷?式
好了今天關于文件系統的內容就是這些,如果有收獲的話還請點個贊支持一下,我們下次再見!