帶你真正認識Linux 系統結構

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

帶你真正認識Linux 系統結構


1. linux內核

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

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

帶你真正認識Linux 系統結構


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

1.1 內存管理

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

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

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

1.2 進程管理

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

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

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

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

1.3 文件系統

和 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在用戶和文件系統之間提供了一個交換層:

帶你真正認識Linux 系統結構


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

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

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

1.4 設備驅動程序

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

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

1.5 網絡接口(NET)

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

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

2. 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版本。

3. linux 文件系統

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

3.1 文件類型

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

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

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

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

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

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

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

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

3.2 Linux目錄

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

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

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

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

帶你真正認識Linux 系統結構


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

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

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

3.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;

[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的文件和目錄所在的地方,需要掛載上一個磁盤分區。

3.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 本地增加的庫

3.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 字節大小的塊。根據塊使用的不同,可分為:

超級塊(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中查出文件屬性及數據存放點,再從數據塊中讀取數據。

帶你真正認識Linux 系統結構


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

帶你真正認識Linux 系統結構


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

帶你真正認識Linux 系統結構


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

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

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

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

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

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

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

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

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

3.6 文件系統在內核中的表示

內核數據結構

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

帶你真正認識Linux 系統結構


文件與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和權限位的概念,這是硬湊出來的。

3.7 掛載文件系統

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 [-參數] [設備名稱] [掛載點]

其中常用的參數有:

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

-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”是要掛載到的目標文件.

3.8 自動掛載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。(如果你非要設成自動掛載,你要確保每次開機時你的光驅和軟驅裡都要有盤,呵呵。)

3.9 軟連接、硬鏈接

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

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

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

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

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

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

具體關係可以看下圖:

帶你真正認識Linux 系統結構


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

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

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

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

3.10 文件目錄管理命令

磁盤和文件空間 :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

4. linux 應用

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

5. linux內核參數優化

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


分享到:


相關文章: