也能夠打開或者關閉 IP 數據包的路由與轉發( routing/forwarding ):
-
# cat /proc/sys/net/ipv4/ip_forward
# echo "1" > /proc/sys/net/ipv4/ip_forward
# echo "0" > /proc/sys/net/ipv4/ip_forward
NFS:
網絡文件操做系統(network file system),容許不一樣的用戶和系統使用 C/S 的方式來共享同一個文件。NFS 容許共享以上的全部文件系統。
Linux 還支持 Microsoft NTFS,vfat 等其它文件系統。在 Linux 內核源碼樹中,Documentation/filesystem 目錄下列有全部支持的文件系統。
使用 mount 命令能夠查看當前掛載的文件系統:
文件系統的幾個基本概念
Inodes
每一個文件都被 inode 數據結構所表示(之前也被寫做i-node)。
每一個 inode 包含系統中一個物理文件的信息。這個文件能夠是目錄,socket,buffer,字符或者字塊設備,符號連接或者常規文件。因此一個 inode 能夠視爲一個實體的信息塊,描述它在磁盤中的位置,大小,時間戳,文件類型,訪問權限和全部者。
Directories
目錄是樹狀的結構。每一個目錄能夠同時包含文件和子目錄。
目錄被看成特殊的文件來實現。實際上,一個目錄就是一個包含了目錄項(directory entry)的文件。每一個目錄項包含一個 inode 號以及一個文件的名字。當一個進程查找一個文件,內核代碼經過路徑在目錄中查找相應的 inode 號。找到 inode 號後,相應的 inode 被加載進內存以做後續使用。
Links
Unix 文件系統實現了連接的概念。
inode 通常關聯一個目錄項。可是,使用硬連接(hard link)可讓一個 inode 關聯多個目錄項。其 inode 中有一個域包含着文件關聯的數量。
建立一個硬連接:
-
# ln /root/file1 /root/file2
建立一個軟連接(symbolic link or soft link):
-
ln -s /path/to/file1.txt /path/to/file2.txt
原理:
從圖中能夠看到,硬連接與原始文件共用一個 inode - 345666,345666 號 inode 如今關聯兩個文件。若是建立的是軟連接,它自己會再新建一個 inode - 966600,這個 96660 號 inode 數據塊地址指向 966699 號 inode。軟連接有點像 windows 的快捷方式。快捷方式自己是個文件,但卻指向另一個地址。而硬連接更像是具備計數功能的別名。
理解了這一張圖就不難理解:
-
$ ln FileAFileB#建立一個硬連接
$ ls -il FileAFileB#具備相同的 inode 號
1482256-rw-r--r-- 2 bruno bruno 21May515:55FileA
1482256-rw-r--r-- 2 bruno bruno 21May515:55FileB
$ rm FileA
$ cat FileB#將看到FileA的內容
$ ln -s FileBFileC#建立軟連接
$ ls -il FileBFileC#FileC文件類型是l-連接文件,且與 FileB 具備不一樣的 inode
1482256-rw-r--r-- 1 bruno bruno 21May515:55FileB
1482226 lrwxrwxrwx 1 bruno bruno 5May516:22FileC->FileB
$ rm FileB
$ cat FileC#提示不存在該文件,皮之不存毛將焉附?
硬連接 VS 軟連接
硬連接 |
軟連接 |
硬連接不能在目錄間建立 |
能夠在不一樣目錄間建立 |
不能跨越文件系統邊界 |
能夠跨文件系統邊界 |
指向源頭,即便源頭被移動或者移除 |
不會更新 |
Device files
類unix操做系統中,能夠能過特別的文件來訪問設備。這些文件並不佔用文件系統的空間,只是一個設備驅動的訪問點。
The Second Extended File system(EXT2)
ext2 是目前 Linux 社區中最成功的文件系統。
像不少其它文件系統,ext2 中的文件也保存在數據塊中。數據塊的大小是固定的,即便不一樣的 ext2 文件系統數據塊的大小多是不一樣的,但一旦 ext2 被建立(mke2fs),這個文件系統中數據塊的大小就被固定了。
每一個文件的大小都被向上取整成整數個塊。若是塊的大小爲 1024B,一個文件的大小爲 1025B,那這個文件須要兩個塊來存儲。
物理佈局:
其中,block 0 老是指向磁盤或者分區的第一個扇區,若是啓動記錄(boot record)存在,那麼必定在 block 0 中。
超級塊(super block)老是位於磁盤或者分區開始的第 1024 字節處。若是一個塊大小爲 1 KB,那麼超級塊位於 block 1。若是一個塊的大小大於 1024B,那麼超級塊位於 block 0。
兩個例子:
表-Floppy Disk 佈局,塊大小爲 1KB
Block Offset |
Length |
Description |
byte 0 |
512 bytes |
boot record (if present) |
byte 512 |
512 bytes |
additional boot record data (if present) |
-- block group 0, blocks 1 to 1439 -- |
byte 1024 |
1024 bytes |
superblock |
block 2 |
1 block |
block group descriptor table |
block 3 |
1 block |
block bitmap |
block 4 |
1 block |
inode bitmap |
block 5 |
23 blocks |
inode table |
block 28 |
1412 blocks |
data blocks |
表-20M 的 ext2 文件系統,使用 1KB 的塊
Block Offset |
Length |
Description |
byte 0 |
512 bytes |
boot record (if present) |
byte 512 |
512 bytes |
additional boot record data (if present) |
-- block group 0, blocks 1 to 8192 -- |
byte 1024 |
1024 bytes |
superblock |
block 2 |
1 block |
block group descriptor table |
block 3 |
1 block |
block bitmap |
block 4 |
1 block |
inode bitmap |
block 5 |
214 blocks |
inode table |
block 219 |
7974 blocks |
data blocks |
-- block group 1, blocks 8193 to 16384 -- |
block 8193 |
1 block |
superblock backup |
block 8194 |
1 block |
block group descriptor table backup |
block 8195 |
1 block |
block bitmap |
block 8196 |
1 block |
inode bitmap |
block 8197 |
214 blocks |
inode table |
block 8408 |
7974 blocks |
data blocks |
-- block group 2, blocks 16385 to 24576 -- |
block 16385 |
1 block |
block bitmap |
block 16386 |
1 block |
inode bitmap |
block 16387 |
214 blocks |
inode table |
block 16601 |
3879 blocks |
data blocks |
ext2—Inode
表—Inode 數據結構
Offset (bytes) |
Size (bytes) |
Description |
0 |
2 |
i_mode |
2 |
2 |
i_uid |
4 |
4 |
i_size |
8 |
4 |
i_atime |
12 |
4 |
i_ctime |
16 |
4 |
i_mtime |
20 |
4 |
i_dtime |
24 |
2 |
i_gid |
26 |
2 |
i_links_count |
28 |
4 |
i_blocks |
32 |
4 |
i_flags |
36 |
4 |
i_osd1 |
40 |
15 x 4 |
i_block |
100 |
4 |
i_generation |
104 |
4 |
i_file_acl |
108 |
4 |
i_dir_acl |
112 |
4 |
i_faddr |
116 |
12 |
i_osd2
|
i_mode:
16 bit,用來代表所描述文件的類型以及訪問權限,可能的值有:
Constant |
Value |
Description |
-- file format -- |
EXT2_S_IFSOCK |
0xC000 |
socket |
EXT2_S_IFLNK |
0xA000 |
symbolic link |
EXT2_S_IFREG |
0x8000 |
regular file |
EXT2_S_IFBLK |
0x6000 |
block device |
EXT2_S_IFDIR |
0x4000 |
directory |
EXT2_S_IFCHR |
0x2000 |
character device |
EXT2_S_IFIFO |
0x1000 |
fifo |
-- process execution user/group override -- |
EXT2_S_ISUID |
0x0800 |
Set process User ID |
EXT2_S_ISGID |
0x0400 |
Set process Group ID |
EXT2_S_ISVTX |
0x0200 |
sticky bit |
-- access rights -- |
EXT2_S_IRUSR |
0x0100 |
user read |
EXT2_S_IWUSR |
0x0080 |
user write |
EXT2_S_IXUSR |
0x0040 |
user execute |
EXT2_S_IRGRP |
0x0020 |
group read |
EXT2_S_IWGRP |
0x0010 |
group write |
EXT2_S_IXGRP |
0x0008 |
group execute |
EXT2_S_IROTH |
0x0004 |
others read |
EXT2_S_IWOTH |
0x0002 |
others write |
EXT2_S_IXOTH |
0x0001 |
others execute |
i_uid:
16 bit,文件所屬用戶的用戶 id
ext2—Block Groups,塊組
多個塊組成一個塊組(Block Group),這樣能夠減小碎片化,而且在讀取大量連續的數據時能夠減小尋道時間(head seeking)。
ext2—Superblock,超級塊
超級塊包含文件系統的全部配置信息,包括文件系統中有多少 inodes 和 blocks,以及它們中有多少是空閒的,在每一個塊組(block group)中有多少 inodes 和 blocks。
超級塊的主拷貝被存儲在磁盤開始 1024 字節處。因爲它對於文件系統的掛載相當重要,整個文件系統的塊組(block group)將會保存它的備份拷貝。
ext2 的第一個版本(修訂號爲 0)在每一個
塊組
的開始處都保存一份超級塊副本。對於大型文件系統來講,這種方法會消耗大量的空間,全部在接下的版本中(修訂號爲 1),能夠將副本保存在指定的塊組中。塊組號能夠選擇 0 ,1 以及以 3,5,7 爲底的冪。
在超級塊中的全部域都以小端模式存儲在磁盤中(其它的 ext2 數據結構也是這樣),這樣 ext2 文件系統在機器間就很方便移植,由於不須要知道文件系統是哪類機器建立的。
超級塊持有的信息有:
魔數(magic number):
標誌 ext2 文件系統的超級塊,掛載軟件(mounting
software)以此來確認這是 ext2 文件系統的超級塊。好比 0xEF53。
修訂級別(revision level):
經過主要和次要的修訂級別,能夠知道當前文件系統是否支持只有在一些特殊修訂版的文件系統中才有的功能特性,以及哪些新的功能特性能安全地應用在當前的文件系統中。
掛載次數及最大掛載次數:
兩個數合起來決定文件系統是否須要全面檢查。每當文件系統被掛載,掛載的次數自增,當它等於最大的掛載次數時,將顯示「達到最大掛載次數,推薦運行 e2fsck」
塊組號:
當前超級塊副本所在的塊組號
塊大小:
文件系統中塊的大小,以字節(byte)爲單位。
每組的塊數:
在一個組內塊的數目。跟塊大小同樣,當文件系統被建立時,這個數量就被固定了。
空閒的塊:
文件系統中空閒的塊。
空間的 inodes:
文件系統中空閒的 inode。
第一個 inode:
ext2 根文件系統中的第一個 inode 是根目錄 ‘/’。
ext2—Block Group Descriptor,組描述符
爲文件系統中的每一個塊組建立一個組描述符。每一個組描述符都表明文件系統中的一個塊組,組描述符中全部信息都只是所描述的塊組的信息。
每一個組描述符
(group descriptor)
包含如下信息
:
Offset (bytes) |
Size (bytes) |
Description |
0 |
4 |
bg_block_bitmap |
4 |
4 |
bg_inode_bitmap |
8 |
4 |
bg_inode_table |
12 |
2 |
bg_free_blocks_count |
14 |
2 |
bg_free_inodes_count |
16 |
2 |
bg_used_dirs_count |
18 |
2 |
bg_pad |
20 |
12 |
bg_reserved |
bg_block_bitmap:
所表示的塊組中 block bitmap 的塊號(block id),32 bit
bg_inode_bitmap:
所表示的塊組中 inode bitmap 的塊號,32 bit
bg_inode_table:
所表示的塊組中 inode table 的塊號,32 bit
bg_free_blocks_count:
所表示的塊組中空閒的塊數,16 bit
bg_free_inodes_count:
所表示的塊組中空閒的 inodes 數量,16 bit
bg_used_dirs_count:
所表示的塊組中 inodes 給目錄用的數量,16 bit
bg_pad:
16 bit,用來使得整個數據結構對齊 32 bit 的邊界
bg_reserved:
12 個保留字節,爲之後的版本留出的空間
ext2—Block Group Descriptor Table,組描述符表
組描述符表(block group descriptor table)是一個組描述符的數組,用來定義全部塊組的參數。包含 inode bitmap,inode table,block bitmap 的位置,以及空閒塊、空閒 inodes 的數量,以及其它有用的信息。它包含全部塊組的信息。
組描述符表跟在超級塊後面。若是塊大小爲 1KB,那麼它將在第三個塊,或者若是塊大小爲 2KB 它將在第二個塊。若是有超級塊的拷貝副本,那麼在超級塊的拷貝副本後面一樣有組描述符表的拷貝副本。
若是塊組有不少,組描述表能夠申請多個塊來存儲相應的組描述符信息。
ext2—Block Bitmap
在小一點的文件系統中,Block Bitmap 位於組塊的第一個塊中(由於小,爲了節省空間因此不放超級塊或者組塊描述符表的備份)。一般它的位置能夠經過讀取塊組相關聯的組描述符中的 bg_block_bitmap 來得到。
每一個位表示塊組中塊的當前狀態,1 表示「已使用」,0 表示 「空閒/可用」。塊組中第一個塊使用第 0 個字節的第 0 個 bit 來表示,相應地,第二個塊用使用第 0 個字節的第 1 個 bit,第八個塊使用第 0 個字節的第 7 個 bit 表示,第 9 個塊使用第 1 個字節的第 0 個 bit 來表示。
ext2—Inode Bitmap
跟 Block Bitmap 相似,不一樣的是,每一個位表示的是 Inode Table 中的 inode 而不是一個塊。
每一個塊組都有一個 inode bitmap,而且位置一樣由塊組對應的組描述符中的 bg_inode_bitmap 決定。
ext2—Inode Table
Inode table 被用來保持追蹤每一個目錄,常規文件,符號連接,或者特殊文件;它們的位置,大小,類型及訪問權限都被保存在 inodes 中。文件名及 inode 是分開的,inode 並不保存文件名,文件名被保存在目錄文件中。
每一個塊組都有一份 inode table,它的位置由組塊對應描述符中的 bg_inode_table 決定。
inode table 中的前幾項會被保留。在版本 0 中有 11 項爲保留項,版本 1 或者後面幾個版本被保留的 inode 項由超級塊結構中的 s_first_ino 指定。
表—已知被保留的 inode 項:
Constant Name |
Value |
Description |
EXT2_BAD_INO |
1 |
bad blocks inode |
EXT2_ROOT_INO |
2 |
root directory inode |
EXT2_ACL_IDX_INO |
3 |
ACL index inode (deprecated?) |
EXT2_ACL_DATA_INO |
4 |
ACL data inode (deprecated?) |
EXT2_BOOT_LOADER_INO |
5 |
boot loader inode |
EXT2_UNDEL_DIR_INO |
6 |
undelete directory inode |
ext2—Directories,目錄
目錄用來有層次地組織文件。每一個目錄都能包含其它目錄,常規文件及特殊文件。
目錄被看成數據塊來保存,並用一個 inode 指向它。指向目錄的 inode 中 i_mode 字段被設定爲 EXT2_S_IFDIR,由此來代表文件類型爲目錄。
在 inode table 中每二個表項的 inode 指向根目錄(root directory)的數據。它是 inode table 的保留項,被指定爲 EXT2_ROOT_INO。
在版本 0 中目錄以鏈表的形式存儲。版本 1 及後面的版本引進索引目錄(indexed directories)。
鏈表形式:
鏈表形式目錄項結構:
Offset (bytes) |
Size (bytes) |
Description |
0 |
4 |
inode |
4 |
2 |
rec_len |
6 |
1 |
name_len |
7 |
1 |
file_type |
8 |
0-255 |
name |
舉個栗子:
inode:
目錄項的 inode。
record length:
目錄項的長度(以字節爲單位)。
name length:
目錄項名字的長度(以字節爲單位)。
file type:
文件類型
典型的文件類型及取值:
Constant Name |
Value |
Description |
EXT2_FT_UNKNOWN |
0 |
Unknown File Type |
EXT2_FT_REG_FILE |
1 |
Regular File |
EXT2_FT_DIR |
2 |
Directory File |
EXT2_FT_CHRDEV |
3 |
Character Device |
EXT2_FT_BLKDEV |
4 |
Block Device |
EXT2_FT_FIFO |
5 |
Buffer File |
EXT2_FT_SOCK |
6 |
Socket File |
EXT2_FT_SYMLINK |
7 |
Symbolic Link |
name:目錄項的名字。
注:
1)版本 0 的 Ext2 使用 2 個字節的 name_len。因爲大部分的實現文件名嚴格限制最大爲 255 個字符,因此這兩個字節被截斷,低字節部分仍是用來存儲文件名,高字節用來存儲文件類型 file_type。這個時候能夠不經過 inode 來查詢文件類型了。這個時候看起來會是這個樣子:
2)目錄項必須 4 字節對齊邊界(沒有任何目錄項會橫跨兩個數據塊)。若是一個目錄項不能塞進一個數據塊中,那麼它就只能放到下一個數據塊中了。
Table . Sample Linked Directory Data Layout, 4KiB blockshtml
Offset (bytes) |
Size (bytes) |
Description |
Directory Entry 0 |
0 |
4 |
inode number: 783362 |
4 |
2 |
record length: 12 |
6 |
1 |
name length: 1 |
7 |
1 |
file type: EXT2_FT_DIR =2 |
8 |
1 |
name: . |
9 |
3 |
padding |
Directory Entry 1 |
12 |
4 |
inode number: 1109761 |
16 |
2 |
record length: 12 |
18 |
1 |
name length: 2 |
19 |
1 |
file type: EXT2_FT_DIR =2 |
20 |
2 |
name: .. |
22 |
2 |
padding |
Directory Entry 2 |
24 |
4 |
inode number: 783364 |
28 |
2 |
record length: 24 |
30 |
1 |
name length: 13 |
31 |
1 |
file type: EXT2_FT_REG_FILE |
32 |
13 |
name: .bash_profile |
45 |
3 |
padding |
Directory Entry 3 |
48 |
4 |
inode number: 783363 |
52 |
2 |
record length: 16 |
54 |
1 |
name length: 7 |
55 |
1 |
file type: EXT2_FT_REG_FILE |
56 |
7 |
name: .bashrc |
63 |
1 |
padding |
Directory Entry 4 |
64 |
4 |
inode number: 783377 |
68 |
2 |
record length: 12 |
70 |
1 |
name length: 4 |
71 |
1 |
file type: EXT2_FT_REG_FILE |
72 |
4 |
name: mbox |
Directory Entry 5 |
76 |
4 |
inode number: 783545 |
80 |
2 |
record length: 20 |
82 |
1 |
name length: 11 |
83 |
1 |
file type: EXT2_FT_DIR =2 |
84 |
11 |
name: public_html |
95 |
1 |
padding |
Directory Entry 6 |
96 |
4 |
inode number: 669354 |
100 |
2 |
record length: 12 |
102 |
1 |
name length: 3 |
103 |
1 |
file type: EXT2_FT_DIR =2 |
104 |
3 |
name: tmp |
107 |
1 |
padding |
Directory Entry 7 |
108 |
4 |
inode number: 0 |
112 |
2 |
record length: 3988 |
114 |
1 |
name length: 0 |
115 |
1 |
file type: EXT2_FT_UNKNOWN |
116 |
0 |
name: |
116 |
3980 |
padding |
索引形式:
一旦文件數量開始增加,連接形式的目錄就會變得很慢。爲了提升性能,基於 hash 的索引用來快速查找文件。
索引目錄根(indexed directory root)
爲了與鏈表形式的目錄兼容,在 block 0 的開始處放置了一些假的目錄項。 . 及 .. 文件夾目錄項就是這些的一部分。
Offset (bytes) |
Size (bytes) |
Description |
-- Linked Directory Entry: . -- |
0 |
4 |
inode: this directory |
4 |
2 |
rec_len: 12 |
6 |
1 |
name_len: 1 |
7 |
1 |
file_type: EXT2_FT_DIR =2 |
8 |
1 |
name: . |
9 |
3 |
padding |
-- Linked Directory Entry: .. -- |
12 |
4 |
inode: parent directory |
16 |
2 |
rec_len: (blocksize - this entry's length(12)) |
18 |
1 |
name_len: 2 |
19 |
1 |
file_type: EXT2_FT_DIR =2 |
20 |
2 |
name: .. |
22 |
2 |
padding |
-- Indexed Directory Root Information Structure -- |
24 |
4 |
reserved, zero |
28 |
1 |
hash_version |
29 |
1 |
info_length |
30 |
1 |
indirect_levels |
31 |
1 |
reserved - unused flags |
hash_version:
1 字節,表示 hash 的版本
info_length:
1 字節,表示索引目錄信息結構體(dx_root)的大小,便是上表中的 Indexed Directory Root Information。
indirect_levels:
1 字節,表示間接索引的層數。在 Linux 2.6.28 中這個值爲 1。
索引目錄項(index directory entry)
索引目錄項關聯一個文件名的哈希值,根據這個哈希值能夠快速地查找到相應的 inode 節點。這些索引目錄項跟在上面說的索引目錄根後面。
它長得像這樣:
Table 4-6. Indexed Directory Entry Structure (dx_entry)node
Offset (bytes) |
Size (bytes) |
Description |
0 |
4 |
hash |
4 |
4 |
block |
hash:
4 字節,文件名的哈希值
block:
4 字節,包含相應文件名的目錄項的 inode 數據塊的索引
目錄的查找算法
1)計算文件名的哈希值
2)讀取 index root
3)使用二分查找查找第一個包含該哈希的子目錄
4)重複第 3 步直到到達樹的最低一層
5)讀取葉子目錄項數據塊,使用常規的查找
6)若是找到了這個文件名,返回該目錄項及 buffer
7)不然,若是下個目錄項的衝突位被設置了,那麼在下一塊數據塊中繼續查找
目錄的插入算法
插入一個新的目錄項到目錄中比之目錄查找要複雜得多。
1)探測要插入的目錄項的索引,過程跟查找同樣
2)若是目標葉子數據塊已經滿了,把它分紅兩份並標記這個數據塊將被插入新的目錄項
3)跟往常同樣插入這個新的目錄項到葉子數據塊
參考資料: