關於Linux系統結構
文章轉自:http://blog.csdn.net/hguisu/article/details/6122513
Linux系統一般有4個主要部分:核心、shell、檔案系統、應用程式。
核心、shell和檔案系統一起形成了基本的作業系統結構,它們使得使用者可以執行程式、管理檔案並使用系統。
1、linux核心
核心是作業系統的核心,具有很多最基本功能,它負責管理系統的程序、記憶體、裝置驅動程式、檔案和網路系統,決定著系統的效能和穩定性。
Linux 核心由如下幾部分組成:記憶體管理、程序管理、裝置驅動程式、檔案系統和網路管理等。如圖:
系統呼叫介面:SCI 層提供了某些機制執行從使用者空間到核心的函式呼叫。這個介面依賴於體系結構,甚至在相同的處理器家族內也是如此。
SCI 實際上是一個非常有用的函式呼叫多路複用和多路分解服務。在 ./linux/kernel 中您可以找到 SCI 的實現,並在 ./linux/arch 中找到依賴於體系結構的部分。
2、記憶體管理
對任何一臺計算機而言,其記憶體以及其它資源都是有限的。為了讓有限的實體記憶體滿足應用程式對記憶體的大需求量,Linux 採用了稱為“虛擬記憶體”的記憶體管理方式。
Linux 將記憶體劃分為容易處理的“記憶體頁”(對於大部分體系結構來說都是 4KB)。Linux 包括了管理可用記憶體的方式,以及物理和虛擬對映所使用的硬體機制。
不過記憶體管理要管理的可不止 4KB 緩衝區。Linux 提供了對 4KB 緩衝區的抽象,例如 slab 分配器。這種記憶體管理模式使用 4KB 緩衝區為基數,然後從中分配結構,並跟蹤記憶體頁使用情況,比如哪些記憶體頁是滿的,哪些頁面沒有完全使用,哪些頁面為空。這樣就允許該模式根據系統需要來動態調整記憶體使用。
為了支援多個使用者使用記憶體,有時會出現可用記憶體被消耗光的情況。由於這個原因,頁面可以移出記憶體並放入磁碟中。這個過程稱為交換,因為頁面會被從記憶體交換到硬碟上。記憶體管理的原始碼可以在 ./linux/mm 中找到。
3.程序管理
程序實際是某特定應用程式的一個執行實體。在 Linux 系統中這一短的時間間隔稱為“時間片”,讓程序輪流執行的方法稱為“程序排程” ,完成排程的程式稱為排程程式。
程序排程控制程序對CPU的訪問。當需要選擇下一個程序執行時,由排程程式選擇最值得執行的程序。
可執行程序實際上是僅等待CPU資源的程序,如果某個程序在等待其它資源,則該程序是不可執行程序。Linux使用了比較簡單的基於優先順序的程序排程演算法選擇新的程序。
通過多工機制,每個程序可認為只有自己獨佔計算機,從而簡化程式的編寫。每個程序有自己單獨的地址空間,並且只能由這一程序訪問,這樣,作業系統避免了程序之間的互相干擾以及“壞”程式對系統可能造成的危害。 為了完成某特定任務,有時需要綜合兩個程式的功能,例如一個程式輸出文字,而另一個程式對文字進行排序。為此,作業系統還提供程序間的通訊機制來幫助完成這樣的任務。Linux 中常見的程序間通訊機制有訊號、管道、共享記憶體、訊號量和套接字等。
核心通過 SCI 提供了一個應用程式程式設計介面(API)來建立一個新程序(fork、exec 或 Portable Operating System Interface [POSⅨ] 函式),停止程序(kill、exit),並在它們之間進行通訊和同步(signal 或者 POSⅨ 機制)。
4.檔案系統
和 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 檔案系統中的檔案一樣使用它們。
5.裝置驅動程式
裝置驅動程式是 Linux 核心的主要部分。和作業系統的其它部分類似,裝置驅動程式執行在高特權級的處理器環境中,從而可以直接對硬體進行操作,但正因為如此,任何一個裝置驅動程式的錯誤都可能導致作業系統的崩潰。裝置驅動程式實際控制作業系統和硬體裝置之間的互動。裝置驅動程式提供一組作業系統可理解的抽象介面 完成和作業系統之間的互動,而與硬體相關的具體操作細節由裝置驅動程式完成。一般而言,裝置驅動程式和裝置的控制晶片有關,例如,如果計算機硬碟是 SCSI 硬碟,則需要使用 SCSI 驅動程式,而不是 IDE 驅動程式。
6.網路介面 NET
提供了對各種網路標準的存取和各種網路硬體的支援。 網路介面可分為網路協議和網路驅動程式。 網路協議部分負責實現每一種可能的網路傳輸協議。眾所周知,TCP/IP 協議是 Internet 的標準協議,同時也是事實上的工業標準。Linux 的網路實現支援 BSD 套接字,支援全部的TCP/IP協議。Linux核心的網路部分由BSD套接字、網路協議層和網路裝置驅動程式組成。 網路裝置驅動程式負責與硬體裝置通訊,每一種可能的硬體裝置都有相應的裝置驅動程式。
7.Linux Shell
shell是系統的使用者介面,提供了使用者與核心進行互動操作的一種介面。它接收使用者輸入的命令並把它送入核心去執行,是一個命令直譯器。另外,shell程式語言具有普通程式語言的很多特點,用這種程式語言編寫的shell程式與其他應用程式具有同樣的效果。目前主要有下列版本的shell。
1.Bourne Shell:是貝爾實驗室開發的。
2.BASH:是GNU的Bourne Again Shell,是GNU作業系統上預設的shell,大部分linux的發行套件使用的都是這種shell。
3.Korn Shell:是對Bourne SHell的發展,在大部分內容上與Bourne Shell相容。
4.C Shell:是SUN公司Shell的BSD版本。
8.linux 檔案系統
檔案系統是檔案存放在磁碟等儲存裝置上的組織方法。Linux系統能支援多種目前流行的檔案系統,如EXT2、 EXT3、 FAT、 FAT32、 VFAT和ISO9660。
8.1 檔案型別
Linux下面的檔案型別主要有:
1) 普通檔案:C語言元程式碼、SHELL指令碼、二進位制的可執行檔案等。分為純文字和二進位制。
2) 目錄檔案:目錄,儲存檔案的唯一地方。
3) 連結檔案:指向同一個檔案或目錄的的檔案。
4) 裝置檔案:與系統外設相關的,通常在/dev下面。分為塊裝置和字元裝置。
5)管道(FIFO)檔案 : 提供程序建通訊的一種方式
6)套接字(socket) 檔案: 該檔案型別與網路通訊有關
可以通過ls –l, file, stat幾個命令來檢視檔案的型別等相關資訊。
8.2 Linux目錄
檔案結構是檔案存放在磁碟等存貯裝置上的組織方法。主要體現在對檔案和目錄的組織上。目錄提供了管理檔案的一個方便而有效的途徑。
Linux使用標準的目錄結構,在安裝的時候,安裝程式就已經為使用者建立了檔案系統和完整而固定的目錄組成形式,並指定了每個目錄的作用和其中的檔案型別。
完整的目錄樹可劃分為小的部分,這些小部分又可以單獨存放在自己的磁碟或分割槽上。這樣,相對穩定的部分和經常變化的部分可單獨存放在不同的分割槽中,從而方便備份或系統管理。目錄樹的主要部分有 root、/usr、/var、/home 等(圖2) 。這樣的佈局可方便在 Linux 計算機之間共享檔案系統的某些部分。
Linux採用的是樹型結構。最上層是根目錄,其他的所有目錄都是從根目錄出發而生成的。
微軟的DOS和windows也是採用樹型結構,但是在DOS和 windows中這樣的樹型結構的根是磁碟分割槽的碟符,有幾個分割槽就有幾個樹型結構,他們之間的關係是並列的。
最頂部的是不同的磁碟(分割槽),如:C,D,E,F等。
但是在linux中,無論作業系統管理幾個磁碟分割槽,這樣的目錄樹只有一個。從結構上講,各個磁碟分割槽上的樹型目錄不一定是並列的。
8.3 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;
[[email protected] ~]# 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的檔案和目錄所在的地方,需要掛載上一個磁碟分割槽。
8.4 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 本地增加的庫
8.5 linux檔案系統
檔案系統指檔案存在的物理空間,linux系統中每個分割槽都是一個檔案系統,都有自己的目錄層次結構。linux會將這些分屬不同分割槽的、單獨的檔案系統按一定的方式形成一個系統的總的目錄層次結構。一個作業系統的執行離不開對檔案的操作,因此要擁有並維護自己的檔案系統。
1.檔案系統型別: 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: 可擦寫的資料光碟檔案系統
2.檔案系統特性
磁碟分割槽完畢後還需要進行格式化(format),之後作業系統才能夠使用這個分割槽。 格式化的目的是能使作業系統可以使用的檔案系統格式(即我們上面 提到檔案系統型別).每種作業系統能夠使用的檔案系統並不相同. 如windows 98 以前的微軟作業系統主要利用的檔案系統是 FAT (或 FAT16),windows 2000 以後的版本有所謂的 NTFS 檔案系統,至於 Linux 的正統檔案系統則為 Ext2 (Linux second extended file system, ext2fs)這一個。此外,在預設的情況下,windows 作業系統是不會認識 Linux 的 Ext2 的。
傳統的磁碟與檔案系統之應用中,一個分割槽就是隻能夠被格式化成為一個檔案系統,所以我們可以說一個 filesystem 就是一個 partition。但是由於新技術的利用,例如我們常聽到的LVM與軟體磁碟陣列(software raid), 這些技術可以將一個分割槽格式化為多個檔案系統(例如LVM),也能夠將多個分割槽合成一個檔案系統(LVM, RAID)! 所以說,目前我們在格式化時已經不再說成針對 partition 來格式化了, 通常我們可以稱呼一個可被掛載的資料為一個檔案系統而不是一個分割槽喔!
那麼檔案系統是如何執行的呢?這與作業系統的檔案資料有關。較新的作業系統的檔案資料 除了檔案實際內容外, 通常含有非常多的屬性,例如 Linux 作業系統的檔案許可權(rwx)與檔案屬性(擁有者、群組、時間引數等)。 檔案系統通常會將這兩部份的資料分別存放在不同的區塊,許可權與屬性放置到 inode 中,至於實際資料則放置到 data block 區塊中。 另外,還有一個超級區塊 (superblock) 會記錄整個檔案系統的整體資訊,包括 inode 與 block 的總量、使用量、剩餘量等。
對於一個磁碟分割槽來說,在被指定為相應的檔案系統後,整個分割槽被分為 1024,2048 和 4096 位元組大小的塊。根據塊使用的不同,可分為: 1.超級塊(Superblock): 這是整個檔案系統的第一塊空間。包括整個檔案系統的基本資訊,如塊大小,inode/block的總量、使用量、剩餘量,指向空間 inode 和資料塊的指標等相關資訊。
2.inode塊(檔案索引節點) : 檔案系統索引,記錄檔案的屬性。它是檔案系統的最基本單元,是檔案系統連線任何子目錄、任何檔案的橋樑。每個子目錄和檔案只有唯一的一個 inode 塊。它包含了檔案系統中檔案的基本屬性(檔案的長度、建立及修改時間、許可權、所屬關係)、存放資料的位置等相關資訊. 在 Linux 下可以通過 “ls -li” 命令檢視檔案的 inode 資訊。硬連線和原始檔具有相同的 inode 。
3.資料塊(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下的快捷方式。
可以刪除原有的檔案而儲存連線檔案,沒有防止誤刪除功能。
這一段的的內容過於抽象,又是節點又是陣列的,我已經儘量通俗再通俗了,又不好加例子作演示。大家如果還是雲裡霧裡的話,我也沒有什麼辦法了,只有先記住,日後在實際應用中慢慢體會、理解了。這也是我學習的一個方法吧。
8.6 檔案系統在核心中的表示
核心資料結構
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和許可權位的概念,這是硬湊出來的。
8.6 掛載檔案系統
linux系統中每個分割槽都是一個檔案系統,都有自己的目錄層次結構。
linux會將這些分屬不同分割槽的、單獨的檔案系統按一定的方式形成一個系統的總的目錄層次結構。這裡所說的“按一定方式”就是指的掛載。
將一個檔案系統的頂層目錄掛到另一個檔案系統的子目錄上,使它們成為一個整體,稱為掛載。把該子目錄稱為掛載點.
例如:
要讀取硬碟中的一個格式化好的分割槽、光碟或軟體等裝置時,必須先把這些裝置對應到某個目錄上,而這個目錄就稱為“掛載點(mount point)”,這樣才可以讀取這些裝置。
掛載後將物理分割槽細節遮蔽掉,使用者只有統一的邏輯概念。所有的東西都是檔案。
注意:
1、掛載點必須是一個目錄。
2、一個分割槽掛載在一個已存在的目錄上, 這個目錄可以不為空,但 掛載後這 個目錄下以前的內容將不可用。對於其他作業系統建立的檔案系統的掛載也是這樣。但是需要理解的是:光碟、軟盤、其他作業系統使用的檔案系統的格式與linux使用的檔案系統格式是不一樣的。
光碟是ISO9660;軟盤是fat16或ext2;windows NT是fat16、NTFS;windows98是fat16、fat32;windows2000和windowsXP是fat16、fat32、 NTFS。
掛載前要了解linux是否支援所要掛載的檔案系統格式。
掛載時使用mount命令,其格式:mount [-引數] [裝置名稱] [掛載點]
其中常用的引數有
-o 指定掛載檔案系統時的選項。有些也可用在/etc/fstab中。
常用的有
codepage=XXX 內碼表iocharset=XXX 字符集
ro 以只讀方式掛載
rw 以讀寫方式掛載
nouser 使一般使用者無法掛載
user 可以讓一般使用者掛載裝置
例如:
1.掛載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等目錄讀寫這些檔案了。
2.掛載光碟:# mk /mnt/cdrom
# mount -t iso9660 /dev/cdrom /mnt/cdrom (關盤的名字一般都是cdrom,這條命令一般都通用)
3.虛擬機器共享資料夾:例如在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”是要掛載到的目標檔案.
8.7 自動掛載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。(如果你非要設成自動掛載,你要確保每次開機時你的光碟機和軟碟機裡都要有盤,呵呵。)
8.8 .軟連線、硬連結
可以用ln命令對一個已經存在的檔案再建立一個新的連線,而不復制檔案的內容。連線有軟連線和硬連線之分,軟連線又叫符號連線。它們各自的特點是:
硬連線:是給檔案一個副本,原檔名和連線檔名都指向相同的實體地址。目錄不能有硬連線;硬連線不能跨越檔案系統(不能跨越不同的分割槽)檔案在磁碟中只有一個拷貝,節省硬碟空間;
修改其中一個,與其連線的檔案同時被修改。如果刪除其中任意一個其餘的檔案將不受影響。
由於刪除檔案要在同一個索引節點屬於唯一的連線時才能成功,因此可以防止不必要的誤刪除。
符號連線(軟連線):用ln -s命令建立檔案的符號連線符號連線是linux特殊檔案的一種,作為一個檔案,它的資料是它所連線的檔案的路徑名。類似windows下的快捷方式。
當然刪除這個連線,也不會影響到原始檔,但對連線檔案的使用、引用都是直接呼叫原始檔的。
具體關係可以看下圖:
8.9.檔案目錄管理命令
磁碟和檔案空間 :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、grep