一文帶你真正認識 Linux 系統結構

Linux 系統一般有 4 個主要部分:內核、shell、文件系統和應用程序。內核、shell 和文件系統一起形成了基本的操作系統結構,它們使得用戶可以運行程序、管理文件並使用系統。

Linux內核

內核是操作系統的核心,具有很多最基本功能,它負責管理系統的進程、內存、設備驅動程序、文件和網絡系統,決定着系統的性能和穩定性。

Linux 內核由如下幾部分組成:內存管理、進程管理、設備驅動程序、文件系統和網絡管理等。如圖:

系統調用接口:SCI 層提供了某些機制執行從用戶空間到內核的函數調用。這個接口依賴於體系結構,甚至在相同的處理器家族內也是如此。SCI 實際上是一個非常有用的函數調用多路複用和多路分解服務。在 ./linux/kernel 中您可以找到 SCI 的實現,並在 ./linux/arch 中找到依賴於體系結構的部分。

內存管理

對任何一臺計算機而言,其內存以及其它資源都是有限的。爲了讓有限的物理內存滿足應用程序對內存的大需求量,Linux 採用了稱爲“虛擬內存”的內存管理方式。Linux 將內存劃分爲容易處理的“內存頁”(對於大部分體系結構來說都是 4KB)。Linux 包括了管理可用內存的方式,以及物理和虛擬映射所使用的硬件機制。

不過內存管理要管理的可不止 4KB 緩衝區。Linux 提供了對 4KB 緩衝區的抽象,例如 SLAB 分配器。這種內存管理模式使用 4KB 緩衝區爲基數,然後從中分配結構,並跟蹤內存頁使用情況,比如哪些內存頁是滿的,哪些頁面沒有完全使用,哪些頁面爲空。這樣就允許該模式根據系統需要來動態調整內存使用。

爲了支持多個用戶使用內存,有時會出現可用內存被消耗光的情況。由於這個原因,頁面可以移出內存並放入磁盤中。這個過程稱爲交換,因爲頁面會被從內存交換到硬盤上。內存管理的源代碼可以在 ./linux/mm 中找到。

進程管理

進程實際是某特定應用程序的一個運行實體。在 Linux 系統中,能夠同時運行多個進程,Linux 通過在短的時間間隔內輪流運行這些進程而實現“多任務”。這一短的時間間隔稱爲“時間片”,讓進程輪流運行的方法稱爲“進程調度” ,完成調度的程序稱爲調度程序。

進程調度控制進程對 CPU 的訪問。當需要選擇下一個進程運行時,由調度程序選擇最值得運行的進程。可運行進程實際上是僅等待 CPU 資源的進程,如果某個進程在等待其它資源,則該進程是不可運行進程。Linux 使用了比較簡單的基於優先級的進程調度算法選擇新的進程。

通過多任務機制,每個進程可認爲只有自己獨佔計算機,從而簡化程序的編寫。每個進程有自己單獨的地址空間,並且只能由這一進程訪問,這樣,操作系統避免了進程之間的互相干擾以及“壞”程序對系統可能造成的危害。爲了完成某特定任務,有時需要綜合兩個程序的功能,例如一個程序輸出文本,而另一個程序對文本進行排序。爲此,操作系統還提供進程間的通訊機制來幫助完成這樣的任務。Linux 中常見的進程間通訊機制有信號、管道、共享內存、信號量和套接字等。

內核通過 SCI 提供了一個應用程序編程接口(API)來創建一個新進程(fork、exec 或 Portable Operating System Interface [POSⅨ] 函數),停止進程(kill、exit),並在它們之間進行通信和同步(signal 或者 POSⅨ 機制)。

文件系統

和 DOS 等操作系統不同,Linux 操作系統中單獨的文件系統並不是由驅動器號或驅動器名稱(如 A: 或 C: 等)來標識的。相反,和 UNIX 操作系統一樣,Linux 操作系統將獨立的文件系統組合成了一個層次化的樹形結構,並且由一個單獨的實體代表這一文件系統。Linux 將新的文件系統通過一個稱爲“掛裝”或“掛上”的操作將其掛裝到某個目錄上,從而讓不同的文件系統結合成爲一個整體。Linux 操作系統的一個重要特點是它支持許多不同類型的文件系統。Linux 中最普遍使用的文件系統是 Ext2,它也是 Linux 土生土長的文件系統。但 Linux 也能夠支持 FAT、VFAT、FAT32、MINIX 等不同類型的文件系統,從而可以方便地和其它操作系統交換數據。由於 Linux 支持許多不同的文件系統,並且將它們組織成了一個統一的虛擬文件系統。

虛擬文件系統(VirtualFileSystem,VFS):隱藏了各種硬件的具體細節,把文件系統操作和不同文件系統的具體實現細節分離了開來,爲所有的設備提供了統一的接口,VFS 提供了多達數十種不同的文件系統。虛擬文件系統可以分爲邏輯文件系統和設備驅動程序。邏輯文件系統指Linux 所支持的文件系統,如 Ext2,FAT 等,設備驅動程序指爲每一種硬件控制器所編寫的設備驅動程序模塊。

虛擬文件系統(VFS)是 Linux 內核中非常有用的一個方面,因爲它爲文件系統提供了一個通用的接口抽象。VFS 在 SCI 和內核所支持的文件系統之間提供了一個交換層。即 VFS 在用戶和文件系統之間提供了一個交換層。

VFS 在用戶和文件系統之間提供了一個交換層:

在 VFS 上面,是對諸如 open、close、read 和 write 之類的函數的一個通用 API 抽象。在 VFS 下面是文件系統抽象,它定義了上層函數的實現方式。它們是給定文件系統(超過 50 個)的插件。文件系統的源代碼可以在 ./linux/fs 中找到。

文件系統層之下是緩衝區緩存,它爲文件系統層提供了一個通用函數集(與具體文件系統無關)。這個緩存層通過將數據保留一段時間(或者隨即預先讀取數據以便在需要時就可用)優化了對物理設備的訪問。緩衝區緩存之下是設備驅動程序,它實現了特定物理設備的接口。

因此,用戶和進程不需要知道文件所在的文件系統類型,而只需要象使用 Ext2 文件系統中的文件一樣使用它們。

設備驅動程序

設備驅動程序是 Linux 內核的主要部分。和操作系統的其它部分類似,設備驅動程序運行在高特權級的處理器環境中,從而可以直接對硬件進行操作,但正因爲如此,任何一個設備驅動程序的錯誤都可能導致操作系統的崩潰。設備驅動程序實際控制操作系統和硬件設備之間的交互。

設備驅動程序提供一組操作系統可理解的抽象接口完成和操作系統之間的交互,而與硬件相關的具體操作細節由設備驅動程序完成。一般而言,設備驅動程序和設備的控制芯片有關,例如,如果計算機硬盤是 SCSI 硬盤,則需要使用 SCSI 驅動程序,而不是 IDE 驅動程序。

網絡接口(NET)

提供了對各種網絡標準的存取和各種網絡硬件的支持。網絡接口可分爲網絡協議和網絡驅動程序。網絡協議部分負責實現每一種可能的網絡傳輸協議。衆所周知,TCP/IP 協議是 Internet 的標準協議,同時也是事實上的工業標準。

Linux 的網絡實現支持 BSD 套接字,支持全部的 TCP/IP 協議。Linux 內核的網絡部分由 BSD 套接字、網絡協議層和網絡設備驅動程序組成。網絡設備驅動程序負責與硬件設備通訊,每一種可能的硬件設備都有相應的設備驅動程序。

Linux Shell

shell是系統的用戶界面,提供了用戶與內核進行交互操作的一種接口。它接收用戶輸入的命令並把它送入內核去執行,是一個命令解釋器。另外,shell 編程語言具有普通編程語言的很多特點,用這種編程語言編寫的 shell 程序與其他應用程序具有同樣的效果。

目前主要有下列版本的 shell。

  • Bourne Shell:是貝爾實驗室開發的。

  • BASH:是 GNU 的 Bourne Again Shell,是 GNU 操作系統上默認的 shell,大部分 Linux 的發行套件使用的都是這種 shell。

  • Korn Shell:是對 Bourne SHell 的發展,在大部分內容上與 Bourne Shell 兼容。

  • C Shell:是 SUN 公司 Shell 的 BSD 版本。

Linux 文件系統

文件系統是文件存放在磁盤等存儲設備上的組織方法。Linux 系統能支持多種目前流行的文件系統,如 Ext2、 Ext3、 FAT、 FAT32、 VFAT 和 ISO9660。

文件類型

Linux 下面的文件類型主要有:

  • 普通文件:C 語言元代碼、SHELL 腳本、二進制的可執行文件等。分爲純文本和二進制。

  • 目錄文件:目錄,存儲文件的唯一地方。

  • 鏈接文件:指向同一個文件或目錄的的文件。

  • 設備文件:與系統外設相關的,通常在 /dev 下面。分爲塊設備和字符設備。

  • 管道(FIFO)文件:提供進程之間通信的一種方式。

  • 套接字(socket)文件:該文件類型與網絡通信有關。

可以通過 ls –l,file,stat 幾個命令來查看文件的類型等相關信息。

Linux 目錄

文件結構是文件存放在磁盤等存貯設備上的組織方法。主要體現在對文件和目錄的組織上。

目錄提供了管理文件的一個方便而有效的途徑。

Linux 使用標準的目錄結構,在安裝的時候,安裝程序就已經爲用戶創建了文件系統和完整而固定的目錄組成形式,並指定了每個目錄的作用和其中的文件類型。

完整的目錄樹可劃分爲小的部分,這些小部分又可以單獨存放在自己的磁盤或分區上。這樣,相對穩定的部分和經常變化的部分可單獨存放在不同的分區中,從而方便備份或系統管理。目錄樹的主要部分有 root、/usr、/var、/home 等。這樣的佈局可方便在 Linux 計算機之間共享文件系統的某些部分。

Linux 採用的是樹型結構。最上層是根目錄,其他的所有目錄都是從根目錄出發而生成的。

微軟的 DOS 和 Windows 也是採用樹型結構,但是在 DOS 和 Windows 中這樣的樹型結構的根是磁盤分區的盤符,有幾個分區就有幾個樹型結構,他們之間的關係是並列的。最頂部的是不同的磁盤(分區),如:C,D,E,F 等。

但是在 Linux 中,無論操作系統管理幾個磁盤分區,這樣的目錄樹只有一個。從結構上講,各個磁盤分區上的樹型目錄不一定是並列的。

Linux 磁盤分區

主分區,擴展分區和邏輯分區:

Linux 分區不同於 Windows,硬盤和硬盤分區在 Linux 都表示爲設備。

硬盤分區一共有三種:主分區,擴展分區和邏輯分區。

硬盤的分區主要分爲主分區(Primary Partion)和擴展分區(Extension Partion)兩種,主分區和擴展分區的數目之和不能大於四個。

主分區(Primary Partion):可以馬上被使用但不能再分區。

擴展分區(Extension Partion):必須再進行分區後才能使用,也就是說它必須還要進行二次分區。

邏輯分區(Logical Partion):由擴展分區建立起來的分區,邏輯分區沒有數量上限制。

擴展分區只不過是邏輯分區的“容器”,實際上只有主分區和邏輯分區進行數據存儲。

Linux下硬盤分區的標識

硬盤分區的標識一般使用 /dev/hd[a-z]X 或者 /dev/sd[a-z]X 來標識,其中 [a-z] 代表硬盤號,X 代表硬盤內的分區號。

整塊硬盤分區的塊號標識:Linux 下用 hda、hdb、sda、sdb 等來標識不同的硬盤。

其中:

IDE 接口硬盤:表示爲 /dev/hda1、/dev/hdb……;

SCSI 接口的硬盤、SATA 接口的硬盤表示爲 /dev/sda、/dev/sdb … … ;

硬盤內的分區:如果X的值是 1 到 4,表示硬盤的主分區(包含擴展分區);邏輯分區從是從 5 開始的,比如 /dev/hda5 肯定是邏輯分區了。

例如:

用 hda1、hda2、 hda5、hda6 來標識不同的分區。其中,字母 a 代表第一塊硬盤,b 代表第二塊硬盤,以此類推。而數字 1 代表一塊硬盤的第一個分區、2 代表第二個分區,依次類推。1 到4 對應的是主分區(Primary Partition)或擴展分區(Extension Partition)。從5開始,對應的都是硬盤的邏輯分區(Logical Partition)。一塊硬盤即使只有一個主分區,邏輯分區也是從 5 開始編號的,這點應特別注意。

總結:一個硬盤分區首先要確認在哪個硬盤,然後再確認它所在硬盤內的哪個分區。

對於 /dev/hda 類似的表示方法,也並不陌生吧;我們在 Linux 通過 fdisk -l 就可以查到硬盤是 /dev/hda 還是 /dev/hdb。

[root@localhost ~]# fdisk -l
Disk /dev/hda: 80.0 GB, 80026361856 bytes
255 heads, 63 sectors/track, 9729 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
/dev/hda1 * 1 970 7791493+ 7 HPFS/NTFS
/dev/hda2 971 9729 70356667+ 5 Extended
/dev/hda5 971 2915 15623181 b W95 FAT32
/dev/hda6 2916 4131 9767488+ 83 linux
/dev/hda7 4132 5590 11719386 83 linux
/dev/hda8 5591 6806 9767488+ 83 linux
/dev/hda9 6807 9657 22900626 83 linux
/dev/hda10 9658 9729 578308+ 82 linux swap / Solaris

請注意第一行, Disk /dev/hda: 80.0 GB, 80026361856 bytes,這個就是表示機器中只有一個硬盤設備 /dev/hda ,體積大小爲 80.0G;下面的就是硬盤的分區,每個分區都有詳細的信息,在這裏不詳細說了。

Linux 下磁盤分區和目錄的關係如下:

  • 任何一個分區都必須掛載到某個目錄上。

  • 目錄是邏輯上的區分。分區是物理上的區分。

  • 磁盤 Linux 分區都必須掛載到目錄樹中的某個具體的目錄上才能進行讀寫操作。

  • 根目錄是所有 Linux 的文件和目錄所在的地方,需要掛載上一個磁盤分區。

Linux 主要目錄的功用

  • /bin 二進制可執行命令

  • /dev 設備特殊文件

  • /etc 系統管理和配置文件

  • /etc/rc.d 啓動的配置文件和腳本

  • /home 用戶主目錄的基點,比如用戶 user 的主目錄就是 /home/user,可以用 ~user 表示

  • /lib 標準程序設計庫,又叫動態鏈接共享庫,作用類似 Windows 裏的 .dll 文件

  • /sbin 系統管理命令,這裏存放的是系統管理員使用的管理程序

  • /tmp 公用的臨時文件存儲點

  • /root 系統管理員的主目錄(呵呵,特權階級)

  • /mnt 系統提供這個目錄是讓用戶臨時掛載其他的文件系統

  • /lost+found 這個目錄平時是空的,系統非正常關機而留下“無家可歸”的文件(Windows 下叫什麼 .chk)就在這裏

  • /proc 虛擬的目錄,是系統內存的映射。可直接訪問這個目錄來獲取系統信息

  • /var 某些大文件的溢出區,比方說各種服務的日誌文件

  • /usr 最龐大的目錄,要用到的應用程序和文件幾乎都在這個目錄。其中包含:

    • /usr/X11R6 存放 X window 的目錄

    • /usr/bin 衆多的應用程序

    • /usr/sbin 超級用戶的一些管理程序/usr/doc linux文檔

    • /usr/include Linux 下開發和編譯應用程序所需要的頭文件

    • /usr/lib 常用的動態鏈接庫和軟件包的配置文件

    • /usr/man 幫助文檔

    • /usr/src 源代碼,Linux 內核的源代碼就放在 /usr/src/linux 裏

    • /usr/local/bin 本地增加的命令

    • /usr/local/lib 本地增加的庫

Linux 文件系統

文件系統指文件存在的物理空間,Linux 系統中每個分區都是一個文件系統,都有自己的目錄層次結構。Linux 會將這些分屬不同分區的、單獨的文件系統按一定的方式形成一個系統的總的目錄層次結構。一個操作系統的運行離不開對文件的操作,因此必然要擁有並維護自己的文件系統。

文件系統類型:

  • Ext2 :早期 Linux 中常用的文件系統

  • Ext3 :Ext2 的升級版,帶日誌功能

  • RAMFS :內存文件系統,速度很快

  • NFS :網絡文件系統,由SUN發明,主要用於遠程文件共享

  • MS-DOS :MS-DOS 文件系統

  • VFAT :Windows 95/98 操作系統採用的文件系統

  • FAT :Windows XP 操作系統採用的文件系統

  • NTFS:Windows NT/XP 操作系統採用的文件系統

  • HPFS :OS/2 操作系統採用的文件系統

  • PROC : 虛擬的進程文件系統

  • ISO9660 :大部分光盤所採用的文件系統

  • ufsSun : OS 所採用的文件系統

  • NCPFS :Novell 服務器所採用的文件系統

  • SMBFS :Samba 的共享文件系統

  • XFS :由SGI開發的先進的日誌文件系統,支持超大容量文件

  • JFS :IBM的AIX使用的日誌文件系統

  • ReiserFS:基於平衡樹結構的文件系統

  • udf:可擦寫的數據光盤文件系統

文件系統特性:

磁盤分區完畢後還需要進行格式化(format),之後操作系統才能夠使用這個分區。格式化的目的是能使操作系統可以使用的文件系統格式(即我們上面提到文件系統類型)。

每種操作系統能夠使用的文件系統並不相同。如 Windows 98 以前的微軟操作系統主要利用的文件系統是 FAT(或 FAT16),Windows 2000 以後的版本有所謂的 NTFS 文件系統,至於 Linux 的正統文件系統則爲 Ext2(Linux second extended file system,Ext2Fsd)這一個。此外,在默認的情況下,Windows 操作系統是不會認識 Linux 的 Ext2 的。

傳統的磁盤與文件系統之應用中,一個分區就是隻能夠被格式化成爲一個文件系統,所以我們可以說一個 filesystem 就是一個 partition。但是由於新技術的利用,例如我們常聽到的 LVM 與軟件磁盤陣列(software raid), 這些技術可以將一個分區格式化爲多個文件系統(例如 LVM),也能夠將多個分區合成一個文件系統(LVM,RAID)!所以說,目前我們在格式化時已經不再說成針對 partition 來格式化了, 通常我們可以稱呼一個可被掛載的數據爲一個文件系統而不是一個分區喔!

那麼文件系統是如何運行的呢?這與操作系統的文件數據有關。較新的操作系統的文件數據除了文件實際內容外, 通常含有非常多的屬性,例如 Linux 操作系統的文件權限(rwx)與文件屬性(擁有者、羣組、時間參數等)。文件系統通常會將這兩部分的數據分別存放在不同的區塊,權限與屬性放置到 inode 中,至於實際數據則放置到 data block 區塊中。另外,還有一個超級區塊(superblock)會記錄整個文件系統的整體信息,包括 inode 與 block 的總量、使用量、剩餘量等。

對於一個磁盤分區來說,在被指定爲相應的文件系統後,整個分區被分爲 1024,2048 和 4096 字節大小的塊。根據塊使用的不同,可分爲:

超級塊(Superblock):這是整個文件系統的第一塊空間。包括整個文件系統的基本信息,如塊大小,inode/block 的總量、使用量、剩餘量,指向空間 inode 和數據塊的指針等相關信息。

inode 塊(文件索引節點):文件系統索引,記錄文件的屬性。它是文件系統的最基本單元,是文件系統連接任何子目錄、任何文件的橋樑。每個子目錄和文件只有唯一的一個 inode 塊。它包含了文件系統中文件的基本屬性(文件的長度、創建及修改時間、權限、所屬關係)、存放數據的位置等相關信息. 在 Linux 下可以通過 “ls -li” 命令查看文件的 inode 信息。硬連接和源文件具有相同的 inode。

數據塊(Block):實際記錄文件的內容,若文件太大時,會佔用多個 block。爲了提高目錄訪問效率,Linux 還提供了表達路徑與 inode 對應關係的 dentry 結構。它描述了路徑信息並連接到節點 inode,它包括各種目錄信息,還指向了 inode 和超級塊。

就像一本書有封面、目錄和正文一樣。在文件系統中,超級塊就相當於封面,從封面可以得知這本書的基本信息;inode 塊相當於目錄,從目錄可以得知各章節內容的位置;而數據塊則相當於書的正文,記錄着具體內容。

Linux 正統的文件系統(如 Ext2、3等)將硬盤分區時會劃分出超級塊、inode Table 區塊和 data block 數據區域。一個文件由一個超級塊、inode 和數據區域塊組成。Inode 包含文件的屬性(如讀寫屬性、owner 等,以及指向數據塊的指針),數據區域塊則是文件內容。當查看某個文件時,會先從 inode table 中查出文件屬性及數據存放點,再從數據塊中讀取數據。

我們將 inode 與 block 區塊用圖解來說明一下,如下圖所示,文件系統先格式化出 inode 與 block 的區塊,假設某一個文件的屬性與權限數據是放置到 inode 4 號(下圖較小方格內),而這個 inode 記錄了文件數據的實際放置點爲 2,7,13,15 這四個 block 號碼,此時我們的操作系統就能夠據此來排列磁盤的閱讀順序,可以一口氣將四個 block 內容讀出來!那麼數據的讀取就如同下圖中的箭頭所指定的模樣了。

這種數據存取的方法我們稱爲索引式文件系統(indexed allocation)。那有沒有其他的慣用文件系統可以比較一下啊?有的,那就是我們慣用的閃盤(閃存),閃盤使用的文件系統一般爲 FAT 格式。FAT 這種格式的文件系統並沒有 inode 存在,所以 FAT 沒有辦法將這個文件的所有 block 在一開始就讀取出來。每個 block 號碼都記錄在前一個 block 當中, 其讀取方式有點像下圖所示:

上圖中我們假設文件的數據依序寫入 1->7->4->15 號這四個 block 號碼中, 但這個文件系統沒有辦法一口氣就知道四個 block 的號碼,他得要一個一個的將 block 讀出後,纔會知道下一個 block 在何處。如果同一個文件數據寫入的 block 分散的太過厲害時,則我們的磁盤讀取頭將無法在磁盤轉一圈就讀到所有的數據, 因此磁盤就會多轉好幾圈才能完整的讀取到這個文件的內容!

常常會聽到所謂的“碎片整理”吧?需要碎片整理的原因就是文件寫入的 block 太過於離散了,此時文件讀取的效能將會變的很差所致。這個時候可以透過碎片整理將同一個文件所屬的 blocks 彙整在一起,這樣數據的讀取會比較容易啊!想當然,FAT 的文件系統需要經常的碎片整理一下,那麼 Ext2 是否需要磁盤重整呢?

由於 Ext2 是索引式文件系統,基本上不太需要常常進行碎片整理的。但是如果文件系統使用太久, 常常刪除/編輯/新增文件時,那麼還是可能會造成文件數據太過於離散的問題,此時或許會需要進行重整一下的。不過,老實說,鳥哥倒是沒有在 Linux 操作系統上面進行過 Ext2/Ext3 文件系統的碎片整理說!似乎不太需要啦!

可以用 ln 命令對一個已經存在的文件再建立一個新的連接,而不復制文件的內容。連接有軟連接和硬連接之分,軟連接又叫符號連接。它們各自的特點是:

硬連接:原文件名和連接文件名都指向相同的物理地址。目錄不能有硬連接;硬連接不能跨越文件系統(不能跨越不同的分區)文件在磁盤中只有一個拷貝,節省硬盤空間;

由於刪除文件要在同一個索引節點屬於唯一的連接時才能成功,因此可以防止不必要的誤刪除。

符號連接:用 ln -s 命令建立文件的符號連接符號連接是 Linux 特殊文件的一種,作爲一個文件,它的數據是它所連接的文件的路徑名。類似 Windows 下的快捷方式。

可以刪除原有的文件而保存連接文件,沒有防止誤刪除功能。

這一段的的內容過於抽象,又是節點又是數組的,我已經儘量通俗再通俗了,又不好加例子作演示。大家如果還是雲裏霧裏的話,我也沒有什麼辦法了,只有先記住,日後在實際應用中慢慢體會、理解了。這也是我學習的一個方法吧。

文件系統在內核中的表示

Linux 內核的 VFS 子系統可以圖示如下:

文件與 IO:每個進程在 PCB(Process Control Block)中都保存着一份文件描述符表,文件描述符就是這個表的索引,每個表項都有一個指向已打開文件的指針,現在我們明確一下:已打開的文件在內核中用 file 結構體表示,文件描述符表中的指針指向 file 結構體。

在 file 結構體中維護 File Status Flag(file 結構體的成員 f_flags)和當前讀寫位置(file 結構體的成員 f_pos)。在上圖中,進程 1 和進程 2 都打開同一文件,但是對應不同的 file 結構體,因此可以有不同的 File Status Flag 和讀寫位置。file 結構體中比較重要的成員還有 f_count,表示引用計數(Reference Count),後面我們會講到,dup、fork 等系統調用會導致多個文件描述符指向同一個 file 結構體,例如有 fd1 和 fd2 都引用同一個 file 結構體,那麼它的引用計數就是 2,當 close(fd1) 時並不會釋放 file 結構體,而只是把引用計數減到 1,如果再 close(fd2),引用計數就會減到 0 同時釋放 file 結構體,這才真的關閉了文件。

每個 file 結構體都指向一個 file_operations 結構體,這個結構體的成員都是函數指針,指向實現各種文件操作的內核函數。比如在用戶程序中 read 一個文件描述符,read 通過系統調用進入內核,然後找到這個文件描述符所指向的 file 結構體,找到 file 結構體所指向的 file_operations 結構體,調用它的 read 成員所指向的內核函數以完成用戶請求。在用戶程序中調用 lseek、read、write、ioctl、open 等函數,最終都由內核調用 file_operations 的各成員所指向的內核函數完成用戶請求。

file_operations 結構體中的 release 成員用於完成用戶程序的 close 請求,之所以叫 release 而不叫 close 是因爲它不一定真的關閉文件,而是減少引用計數,只有引用計數減到0才關閉文件。對於同一個文件系統上打開的常規文件來說,read、write 等文件操作的步驟和方法應該是一樣的,調用的函數應該是相同的,所以圖中的三個打開文件的 file 結構體指向同一個 file_operations 結構體。如果打開一個字符設備文件,那麼它的 read、write 操作肯定和常規文件不一樣,不是讀寫磁盤的數據塊而是讀寫硬件設備,所以 file 結構體應該指向不同的 file_operations 結構體,其中的各種文件操作函數由該設備的驅動程序實現。

每個 file 結構體都有一個指向 dentry 結構體的指針,“dentry”是 directory entry(目錄項)的縮寫。我們傳給 open、stat 等函數的參數的是一個路徑,例如 /home/akaedu/a,需要根據路徑找到文件的 inode。爲了減少讀盤次數,內核緩存了目錄的樹狀結構,稱爲 dentry cache,其中每個節點是一個 dentry 結構體,只要沿着路徑各部分的 dentry 搜索即可,從根目錄/找到 home 目錄,然後找到 akaedu 目錄,然後找到文件 a。dentry cache 只保存最近訪問過的目錄項,如果要找的目錄項在 cache 中沒有,就要從磁盤讀到內存中。

每個 dentry 結構體都有一個指針指向 inode 結構體。inode 結構體保存着從磁盤 inode 讀上來的信息。在上圖的例子中,有兩個 dentry,分別表示 /home/akaedu/a 和 /home/akaedu/b,它們都指向同一個 inode,說明這兩個文件互爲硬鏈接。inode 結構體中保存着從磁盤分區的 inode 讀上來信息,例如所有者、文件大小、文件類型和權限位等。每個 inode 結構體都有一個指向 inode_operations 結構體的指針,後者也是一組函數指針指向一些完成文件目錄操作的內核函數。

和 file_operations 不同,inode_operations 所指向的不是針對某一個文件進行操作的函數,而是影響文件和目錄佈局的函數,例如添加刪除文件和目錄、跟蹤符號鏈接等等,屬於同一文件系統的各 inode 結構體可以指向同一個 inode_operations 結構體。

inode 結構體有一個指向 super_block 結構體的指針。super_block 結構體保存着從磁盤分區的超級塊讀上來的信息,例如文件系統類型、塊大小等。super_block 結構體的 s_root 成員是一個指向 dentry 的指針,表示這個文件系統的根目錄被 mount 到哪裏,在上圖的例子中這個分區被 mount 到 /home 目錄下。

file、dentry、inode、super_block 這幾個結構體組成了 VFS 的核心概念。對於 Ext2 文件系統來說,在磁盤存儲佈局上也有 inode 和超級塊的概念,所以很容易和 VFS 中的概念建立對應關係。而另外一些文件系統格式來自非 UNIX 系統(例如 Windows 的 FAT32、NTFS),可能沒有 inode 或超級塊這樣的概念,但爲了能 mount 到 Linux 系統,也只好在驅動程序中硬湊一下,在 Linux 下看 FAT32 和 NTFS 分區會發現權限位是錯的,所有文件都是 rwxrwxrwx,因爲它們本來就沒有 inode 和權限位的概念,這是硬湊出來的。

掛載文件系統

Linux 系統中每個分區都是一個文件系統,都有自己的目錄層次結構。linux 會將這些分屬不同分區的、單獨的文件系統按一定的方式形成一個系統的總的目錄層次結構。這裏所說的“按一定方式”就是指的掛載。

將一個文件系統的頂層目錄掛到另一個文件系統的子目錄上,使它們成爲一個整體,稱爲掛載。把該子目錄稱爲掛載點。

例如要讀取硬盤中的一個格式化好的分區、光盤或軟件等設備時,必須先把這些設備對應到某個目錄上,而這個目錄就稱爲“掛載點(mount point)”,這樣纔可以讀取這些設備。掛載後將物理分區細節屏蔽掉,用戶只有統一的邏輯概念。所有的東西都是文件。

注意:

  • 掛載點必須是一個目錄。

  • 一個分區掛載在一個已存在的目錄上,這個目錄可以不爲空,但掛載後這個目錄下以前的內容將不可用。

對於其他操作系統建立的文件系統的掛載也是這樣。但是需要理解的是:光盤、軟盤、其他操作系統使用的文件系統的格式與 Linux 使用的文件系統格式是不一樣的。光盤是 ISO9660;軟盤是 FAT16 或 Ext2;Windows NT 是 FAT16、NTFS;Windows 98是 FAT16、FAT32;Windows 2000 和 Windows XP 是FAT16、FAT32、 NTFS。掛載前要了解 Linux 是否支持所要掛載的文件系統格式。

掛載時使用 mount 命令,其格式:mount [-參數] [設備名稱] [掛載點]。

其中常用的參數有:

-t 指定設備的文件系統類型(什麼提到的文件類型)。

-o 指定掛載文件系統時的選項。有些也可用在 /etc/fstab 中。常用的有:

codepage=XXX 代碼頁
iocharset=XXX 字符集
ro 以只讀方式掛載
rw 以讀寫方式掛載
nouser 使一般用戶無法掛載
user 可以讓一般用戶掛載設備

例如:

掛載 Windows 的文件系統:

1、首先我們使用 sudo fdisk -l 查看掛載的設備,例如最下面有:/dev/hda5。

2、mkdir 創建一個目錄,這裏的目錄是作爲掛在目錄,就是你要把 E 盤掛到這個目錄下:mk /mnt/winc。

3、Windows 和 Linux 使用的不是一個文件系統,一般情況下 Linux 不掛載 Windows 文件系統,所以要你手動 mount:

# mount -t vfat /dev/hda5 /mnt/winc ( -t vfat 指出這裏的文件系統 FAT32)

現在就可以進入 /mnt/winc 等目錄讀寫這些文件了。

掛載光盤:# mk /mnt/cdrom

# mount -t iso9660 /dev/cdrom /mnt/cdrom(光盤的名字一般都是 cdrom,這條命令一般都通用)

虛擬機共享文件夾:例如在 VirtualBox 下,主機是 Windows,Ubuntu 是 Guest。共分三步:

1、首先要安裝虛擬電腦工具包:

在 VirtualBox 的菜單裏選擇“設備”->“安裝虛擬電腦工具包”,你會發現在 Ubuntu 桌面上多出一個光盤圖標,這張光盤默認被自動加載到了文件夾 /media/cdom0,而且 /cdrom 自動指向這個文件夾。默認設置下文件管理器會自動打開這張光盤,可以看到裏面有個“VBoxLinuxAdditions.run”文件。打開一個命令行終端,依次輸入“cd /cdrom”和“sudo sh ./VBoxLinuxAdditions.run”,不含雙引號,開始安裝工具包。安裝完畢,會用英文提示要重啓 Ubuntu,建議立刻重啓。重啓後,比較明顯的變化是鼠標是共享模式,並且剪貼板也和 Windows共享了。如果有這些變化,說明虛擬電腦工具包已經裝成功。

2、下一步設置共享文件夾

在共享文件夾設置窗口中,單擊右側的“添加一個共享文件夾”,路徑選擇你想要共享的Windows文件夾,共享名任取一個自己喜歡的,比如“myshare”,選項 read-only 是指是否只允許 Ubuntu 讀這個文件夾,請根據需要選擇這個選項。

3、在 Ubuntu 下掛載這個共享文件夾:sudo mount -t vboxsf myshare /media/share

其中“myshare”是之前取的共享文件夾的名字,“/media/share”是要掛載到的目標文件。

自動掛載 Windows 分區

每次開機訪問 Windows 分區都要運行 mount 命令顯然太煩瑣,爲什麼訪問其他的 Linux 分區不用使用 mount 命令呢?

其實,每次開機時,Linux 自動將需要掛載的 Linux 分區掛載上了。那麼我們是不是可以設定讓 Linux 在啓動的時候也掛載我們希望掛載的分區,如 Windows 分區,以實現文件系統的自動掛載呢?

這是完全可以的。在 /etc 目錄下有個 fstab 文件,它裏面列出了 Linux 開機時自動掛載的文件系統的列表。我的 /etc/fstab 文件如下:

/dev/hda2 / ext3 defaults 1 1
/dev/hda1 /boot ext3 defaults 1 2
none /dev/pts devpts gid=5,mode=620 0 0
none /proc proc defaults 0 0
none /dev/shm tmpfs defaults 0 0
/dev/hda3 swap swap defaults 0 0
/dev/cdrom /mnt/cdrom iso9660 noauto,codepage=936,iocharset=gb2312 0 0
/dev/fd0 /mnt/floppy auto noauto,owner,kudzu 0 0
/dev/hdb1 /mnt/winc vfat defaults,codepage=936,iocharset=cp936 0 0
/dev/hda5 /mnt/wind vfat defaults,codepage=936,iocharset=cp936 0 0

在 /etc/fstab 文件裏,第一列是掛載的文件系統的設備名,第二列是掛載點,第三列是掛載的文件系統類型,第四列是掛載的選項,選項間用逗號分隔。第五六列不知道是什麼意思,還望高手指點。

在最後兩行是我手工添加的 Windows 下的 C、D盤,加了 codepage=936 和 iocharset=cp936 參數以支持中文文件名。參數 defaults 實際上包含了一組默認參數:

  • rw 以可讀寫模式掛載

  • suid 開啓用戶 ID 和羣組 ID 設置位

  • dev 可解讀文件系統上的字符或區塊設備

  • exec 可執行二進制文件

  • auto 自動掛載

  • nouser 使一般用戶無法掛載

  • async 以非同步方式執行文件系統的輸入輸出操作

大家可以看到在這個列表裏,光驅和軟驅是不自動掛載的,參數設置爲 noauto。(如果你非要設成自動掛載,你要確保每次開機時你的光驅和軟驅裏都要有盤,呵呵。)

軟連接、硬鏈接

可以用 ln 命令對一個已經存在的文件再建立一個新的連接,而不復制文件的內容。連接有軟連接和硬連接之分,軟連接又叫符號連接。它們各自的特點是:

硬連接:是給文件一個副本,原文件名和連接文件名都指向相同的物理地址。目錄不能有硬連接;硬連接不能跨越文件系統(不能跨越不同的分區)文件在磁盤中只有一個拷貝,節省硬盤空間。

修改其中一個,與其連接的文件同時被修改。如果刪除其中任意一個其餘的文件將不受影響。

由於刪除文件要在同一個索引節點屬於唯一的連接時才能成功,因此可以防止不必要的誤刪除。

符號連接(軟連接):用 ln -s 命令建立文件的符號連接符號連接是linux特殊文件的一種,作爲一個文件,它的數據是它所連接的文件的路徑名。類似 Windows 下的快捷方式。

當然刪除這個連接,也不會影響到源文件,但對連接文件的使用、引用都是直接調用源文件的。

具體關係可以看下圖:

從圖上可以看出硬鏈接和軟鏈接的區別:

  • 硬鏈接原文件和新文件的 inode 編號一致,而軟鏈接不一樣。

  • 對原文件刪除,會導致軟鏈接不可用,而硬鏈接不受影響。

  • 對原文件的修改,軟、硬鏈接文件內容也一樣的修改,因爲都是指向同一個文件內容的。

文件目錄管理命令

磁盤和文件空間 :fdisk df du

文件目錄與管理:cd pwd mkdir rmdir ls cp rm mv

查看文件內容 cat、tac、more、less、head 、tail

文件目錄與權限 :chmod chown chgrp umask

文件查找:which、whereis、locate、find、find

Linux 應用

標準的 Linux 系統一般都有一套都有稱爲應用程序的程序集,它包括文本編輯器、編程語言、X Window、辦公套件、Internet 工具和數據庫等。

Linux 內核參數優化

內核參數是用戶和系統內核之間交互的一個接口,通過這個接口,用戶可以在系統運行的同時動態更新內核配置,而這些內核參數是通過 Linux Proc 文件系統存在的。因此,可以通過調整 Proc 文件系統達到優化 Linux 性能的目的。

原文鏈接:https://www.jianshu.com/p/85b255a73761

Kubernetes管理員認證(CKA)培訓

本次CKA培訓在北京開班,基於最新考綱,通過線下授課、考題解讀、模擬演練等方式,幫助學員快速掌握Kubernetes的理論知識和專業技能,並針對考試做特別強化訓練,讓學員能從容面對CKA認證考試,使學員既能掌握Kubernetes相關知識,又能通過CKA認證考試,學員可多次參加培訓,直到通過認證。點擊下方圖片或者閱讀原文鏈接查看詳情。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章