Linux內(nèi)核知識(shí)

首先來(lái)一張圖說(shuō)明GNU/Linux的基本的體系結(jié)構(gòu):


Linux 內(nèi)核可以進(jìn)一步劃分成 3 層:最上面是系統(tǒng)調(diào)用接口,用戶(hù)程序通過(guò)軟件中斷后,調(diào)用系統(tǒng)內(nèi)核提供的功能,這個(gè)在用戶(hù)空間和內(nèi)核提供的服務(wù)之間的接口稱(chēng)為系統(tǒng)調(diào)用;系統(tǒng)調(diào)用接口之下是內(nèi)核代碼,可以更精確地定義為獨(dú)立于體系結(jié)構(gòu)的內(nèi)核代碼,這些代碼是 Linux 所支持的所有處理器體系結(jié)構(gòu)所通用的;內(nèi)核代碼之下是依賴(lài)于體系結(jié)構(gòu)的代碼,構(gòu)成了通常稱(chēng)為 BSP(Board Support Package)的部分,這些代碼用作給定體系結(jié)構(gòu)的處理器和特定于平臺(tái)的代碼。

用戶(hù)模式和內(nèi)核模式

執(zhí)行進(jìn)程的模式有兩種:用戶(hù)模式和內(nèi)核模式。你編寫(xiě)的代碼和執(zhí)行所鏈接的庫(kù)運(yùn)行在用戶(hù)模式下。需要內(nèi)核服務(wù)時(shí)執(zhí)行的內(nèi)核代碼只能在內(nèi)核模式下運(yùn)行。這是為了安全性考慮,用戶(hù)模式可以確保一個(gè)進(jìn)程只能訪問(wèn)自己的內(nèi)存空間,如果破壞了自己內(nèi)部結(jié)構(gòu),它也只能影響到自己,而不涉及其它的進(jìn)程,更不會(huì)影響到整個(gè)系統(tǒng)。在用戶(hù)模式下,進(jìn)程能訪問(wèn)的內(nèi)存稱(chēng)為用戶(hù)空間。內(nèi)核需要維護(hù)數(shù)據(jù)結(jié)構(gòu)以控制系統(tǒng)中每個(gè)進(jìn)程,它提供了一個(gè)所有進(jìn)程共享的內(nèi)存區(qū)域,為了保證安全性,內(nèi)核代碼和數(shù)據(jù)結(jié)構(gòu)必須嚴(yán)格獨(dú)立于用戶(hù)代碼和數(shù)據(jù),只有內(nèi)存代碼可以在內(nèi)核模式下運(yùn)行,訪問(wèn)的共享內(nèi)核數(shù)據(jù)以及執(zhí)行權(quán)限指令。把進(jìn)程在內(nèi)核模式下訪問(wèn)的內(nèi)存區(qū)域叫做內(nèi)核空間。內(nèi)核空間只有一個(gè),在內(nèi)核模式下的進(jìn)程才能訪問(wèn),但是內(nèi)核空間是每個(gè)進(jìn)程所特有的。

在典型的32位系統(tǒng)下虛擬地址為3G/1G的分配方式。內(nèi)核空間位于高地址0xC0000000-0xFFFFFFFF,而實(shí)際的物理地址對(duì)應(yīng)的是0x00000000-0x3FFFFFFF

系統(tǒng)調(diào)用

進(jìn)程通過(guò)系統(tǒng)調(diào)用進(jìn)入和退出內(nèi)核模式,許多POSIX函數(shù)是系統(tǒng)調(diào)用的簡(jiǎn)單封裝,如open,close,ictol,write和read等。驅(qū)動(dòng)設(shè)備只能在內(nèi)核模式下執(zhí)行,應(yīng)用程序不能直接調(diào)用設(shè)備驅(qū)動(dòng)程序,而是使用預(yù)定義的系統(tǒng)調(diào)用間接的訪問(wèn)驅(qū)動(dòng)程序代碼。
下面是系統(tǒng)調(diào)用read的一個(gè)例子:

#include <syscall.h>
….
n = syscall(SYS_read, fd, buffer, length)

Linux提供的系統(tǒng)調(diào)用列表由內(nèi)核版本決定,并且不隨時(shí)間變化而變化。然而,用于創(chuàng)建系統(tǒng)調(diào)用的機(jī)制卻會(huì)因?yàn)椴煌幚砥黧w系結(jié)構(gòu)而不同。系統(tǒng)調(diào)用函數(shù)是一個(gè)用于創(chuàng)建系統(tǒng)調(diào)用的匯編代碼的封裝。命令strace對(duì)于追蹤系統(tǒng)調(diào)用非常有用,因?yàn)槔盟梢灾喇?dāng)前任務(wù)執(zhí)行的情況。
通常用戶(hù)代碼先將參數(shù)壓入堆?;蛘弑4嬖陬A(yù)定義的寄存器中,然后在使用中斷調(diào)用系統(tǒng)調(diào)用處理器。中斷處理器將進(jìn)程轉(zhuǎn)入到內(nèi)核模式,并調(diào)用適當(dāng)?shù)南到y(tǒng)調(diào)用。在內(nèi)核模式下,它從寄存器中讀取參數(shù)或使用特定的函數(shù)從用戶(hù)空間復(fù)制參數(shù)。可移植程序不能直接使用系統(tǒng)調(diào)用,而是依賴(lài)庫(kù)為其實(shí)現(xiàn)系統(tǒng)調(diào)用。系統(tǒng)調(diào)用隨著操作系統(tǒng)版本變化而變化,庫(kù)的調(diào)用則無(wú)需這些變化。
Linux使用syscall技術(shù)稱(chēng)為應(yīng)用程序二進(jìn)制接口(ABI),它并不是Linux所獨(dú)有的。該技術(shù)可以用于其它操作系統(tǒng),甚至是BOIS系統(tǒng)。它與API是不同的,API要求鏈接兼容的函數(shù),而ABI步要求鏈接不需要運(yùn)行的代碼。這是可執(zhí)行程序無(wú)需重建就可以在許多不同內(nèi)核中運(yùn)行的原因之一。一個(gè)運(yùn)行在2.2內(nèi)核下的靜態(tài)鏈接的可執(zhí)行程序可能在2.6內(nèi)核下仍然可以運(yùn)行,因?yàn)榇蠖鄶?shù)常見(jiàn)的系統(tǒng)調(diào)用接口從不會(huì)變化。

用戶(hù)空間和內(nèi)核空間的數(shù)據(jù)傳遞

用戶(hù)模式下的內(nèi)核空間是不可見(jiàn)的,當(dāng)訪問(wèn)用戶(hù)空間時(shí),內(nèi)核模式也必須格外注意。因此,通過(guò)系統(tǒng)調(diào)用傳送數(shù)據(jù)非常的麻煩。雖然簡(jiǎn)單的參數(shù)可以通過(guò)寄存器傳遞,但是大型的內(nèi)存必須通過(guò)復(fù)制,導(dǎo)致效率相當(dāng)?shù)牡拖?。一些系統(tǒng)調(diào)用(read/write)需要在用戶(hù)模式和內(nèi)核模式之間傳遞大量數(shù)據(jù),雖然這些額外的復(fù)制作用不大,但是它能維持內(nèi)核空間和用戶(hù)空間的相對(duì)獨(dú)立。
雖然復(fù)制在短期看來(lái)會(huì)降低程序的性能,但從長(zhǎng)遠(yuǎn)來(lái)看它有助于性能的提高,例如文件系統(tǒng)高速緩存,當(dāng)數(shù)據(jù)寫(xiě)入文件時(shí),數(shù)據(jù)被寫(xiě)入磁盤(pán)之前會(huì)先寫(xiě)入到內(nèi)核空間,所以write這個(gè)動(dòng)作可以在后臺(tái)完成,應(yīng)用程序可以通過(guò)flush來(lái)刷新用戶(hù)空間的緩沖,使得程序繼續(xù)執(zhí)行。

進(jìn)程調(diào)度程序

解決多任務(wù)操作系統(tǒng)問(wèn)題的算法叫做程序調(diào)度(Scheduler),Linux內(nèi)核提供多種調(diào)度算法,并且允許用戶(hù)在系統(tǒng)安裝時(shí)選擇合適的調(diào)度算法。
調(diào)度程序的調(diào)用通常嵌入到系統(tǒng)調(diào)用中,并在進(jìn)程需要等待事件時(shí)發(fā)生。一個(gè)與設(shè)備進(jìn)行大量通信的進(jìn)程會(huì)經(jīng)常調(diào)用調(diào)度程序,由于設(shè)備的速度很慢,進(jìn)程的大部分運(yùn)行時(shí)間都浪費(fèi)在等待過(guò)程中,這樣運(yùn)行時(shí)不會(huì)耗費(fèi)太多的CPU時(shí)間。
注:何為協(xié)同多任務(wù)處理(Cooperativer multitasking)。
一個(gè)進(jìn)程若不進(jìn)行I/O,那就會(huì)占用大量的CPU時(shí)間,從而使得其它進(jìn)程無(wú)法使用CPU,此時(shí)需要采用搶占式任務(wù)處理(Preemptive multitasking)。
每個(gè)Linux進(jìn)程都有一個(gè)執(zhí)行時(shí)間片或quantum,當(dāng)一個(gè)進(jìn)程因?yàn)闀r(shí)間片使用完被內(nèi)核停止執(zhí)行時(shí),這個(gè)進(jìn)程被搶占,如果有一個(gè)享有更高優(yōu)先級(jí)的進(jìn)程在就緒隊(duì)列中,內(nèi)核同樣可以搶占正在執(zhí)行的進(jìn)程。一個(gè)進(jìn)程也可以自動(dòng)放棄CPU,可以通過(guò)sched_yield系統(tǒng)調(diào)用來(lái)放棄CPU。也可以通過(guò)其它系統(tǒng)調(diào)用(sleep)來(lái)實(shí)現(xiàn)對(duì)CPU的放棄。當(dāng)進(jìn)程在內(nèi)核模式下等待一個(gè)事件時(shí),稱(chēng)為阻塞(blocking)。一個(gè)阻塞進(jìn)程既不會(huì)占用CPU,也不會(huì)被調(diào)度程序使用。
所有搶占式多任務(wù)處理操作系統(tǒng)都實(shí)現(xiàn)了按優(yōu)先級(jí)調(diào)度策略。高優(yōu)先權(quán)的進(jìn)程總是比低優(yōu)先級(jí)的進(jìn)程先被調(diào)度。雖然用戶(hù)可以影響進(jìn)程的優(yōu)先級(jí),但進(jìn)程的優(yōu)先級(jí)最終還是由內(nèi)核決定。Linux內(nèi)核通過(guò)使用動(dòng)態(tài)優(yōu)先級(jí)(Dynamic Priority),不斷提高和降低正在運(yùn)行進(jìn)程的優(yōu)先級(jí),從而使得低優(yōu)先級(jí)的進(jìn)程也能運(yùn)行。
Linux內(nèi)核調(diào)度策略一個(gè)重要目的是保證所有進(jìn)程都有機(jī)會(huì)被調(diào)度,也就是說(shuō)每個(gè)任務(wù)都有相應(yīng)的使用CPU的時(shí)間。進(jìn)程的有效優(yōu)先級(jí)就是靜態(tài)優(yōu)先級(jí)和額外值之和,這個(gè)額外值可正可負(fù)。
ps命令選項(xiàng)中-C顯示進(jìn)程與參數(shù)的配對(duì)項(xiàng),如-C <proc_name>,-o用于控制輸出的格式,如etime,pid,pri,cmd。
內(nèi)核允許用戶(hù)通過(guò)使用一個(gè)名為nice的數(shù)值來(lái)影響調(diào)度程序關(guān)于優(yōu)先級(jí)的調(diào)度。正的nice可以降低優(yōu)先級(jí),負(fù)的nice可以提高優(yōu)先級(jí)。請(qǐng)查看nice和renice命令。

實(shí)時(shí)優(yōu)先權(quán)

響應(yīng)時(shí)間是指軟件響應(yīng)外部事件的時(shí)間,比如中斷。嚴(yán)格的響應(yīng)時(shí)間的應(yīng)用程序通常被稱(chēng)為實(shí)時(shí)應(yīng)用程序。Linux中實(shí)時(shí)進(jìn)程的優(yōu)先級(jí)范圍是41-139,實(shí)時(shí)優(yōu)先級(jí)越大,優(yōu)先級(jí)越高。實(shí)時(shí)優(yōu)先級(jí)在整個(gè)生命周期中值是不變的。
在設(shè)計(jì)實(shí)時(shí)進(jìn)程時(shí),必須確定它的調(diào)度策略,POSIX為實(shí)時(shí)進(jìn)程指定了兩種策略:先進(jìn)先出(FIFO)和時(shí)間片法(round robin)。
創(chuàng)建實(shí)時(shí)進(jìn)程的方法就是使用chrt命令,chrt在內(nèi)部調(diào)用fork和exec和POSIX函數(shù)來(lái)設(shè)置優(yōu)先級(jí),函數(shù)如下:
int sched_setscheduler(pid_t pid, int policy, const struct sched_paramp);
int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param
p);
int sched_get_priority_min/max(int policy);
第一個(gè)為進(jìn)程服務(wù),第二個(gè)為線程服務(wù)。

sodu chrt --fifo 50 ./chewer &


Linux內(nèi)核源碼基礎(chǔ)、

對(duì)于Linux內(nèi)核的單內(nèi)核模式的系統(tǒng),可以把它分為如下:


Linux內(nèi)核又可以分為5個(gè)大的模塊:主要由進(jìn)程調(diào)度(SCHED)、內(nèi)存管理(MM)、虛擬文件系統(tǒng)(VFS)、網(wǎng)絡(luò)接口(NET)和進(jìn)程間通信(IPC)五個(gè)子系統(tǒng)組成。

Linux中進(jìn)程間通信機(jī)制包括:管道(有名管道和無(wú)名管道)、消息隊(duì)列、信號(hào)、套接字、共享內(nèi)存、信號(hào)量。Linux中線程間的通信機(jī)制主要有:鎖機(jī)制(包括互斥鎖、條件變量、讀寫(xiě)鎖)、信號(hào)量機(jī)制(Semaphore:包括無(wú)名線程信號(hào)量和命名線程信號(hào)量)、信號(hào)機(jī)制(Signal:類(lèi)似進(jìn)程間的信號(hào)處理)。線程間通信的作用主要是用于線程之間的同步,所以線程間沒(méi)有像進(jìn)程通信中的用于數(shù)據(jù)交換的機(jī)制

Linux內(nèi)核模塊
Linux內(nèi)核的組成部分的關(guān)系

1. 進(jìn)程調(diào)度

進(jìn)程調(diào)度控制系統(tǒng)中的多個(gè)進(jìn)程對(duì)CPU的訪問(wèn),使得多個(gè)進(jìn)程能在CPU中“微觀串行,宏觀并行”地執(zhí)行。進(jìn)程調(diào)度處于系統(tǒng)的中心位置,內(nèi)核中其他的子系統(tǒng)都依賴(lài)它,因?yàn)槊總€(gè)子系統(tǒng)都需要掛起或恢復(fù)進(jìn)程。

Linux進(jìn)程狀態(tài)轉(zhuǎn)換

Linux的進(jìn)程在幾個(gè)狀態(tài)間進(jìn)行切換。在設(shè)備驅(qū)動(dòng)編程中,當(dāng)請(qǐng)求的資源不能得到滿(mǎn)足時(shí),驅(qū)動(dòng)一般會(huì)調(diào)度其他進(jìn)程執(zhí)行,并使本進(jìn)程進(jìn)入睡眠狀態(tài),直到它請(qǐng)求的資源被釋放,才會(huì)被喚醒而進(jìn)入就緒態(tài)。睡眠分成可被打斷的睡眠和不可被打斷的睡眠,兩者的區(qū)別在于可被打斷的睡眠在收到信號(hào)的時(shí)候會(huì)醒。在設(shè)備驅(qū)動(dòng)編程中,當(dāng)請(qǐng)求的資源不能得到滿(mǎn)足時(shí),驅(qū)動(dòng)一般會(huì)調(diào)度其他進(jìn)程執(zhí)行,其對(duì)應(yīng)進(jìn)程進(jìn)入睡眠狀態(tài),直到它請(qǐng)求的資源被釋放,才會(huì)被喚醒而進(jìn)入就緒態(tài)。設(shè)備驅(qū)動(dòng)中,如果需要幾個(gè)并發(fā)執(zhí)行的任務(wù),可以啟動(dòng)內(nèi)核線程,啟動(dòng)內(nèi)核線程的函數(shù)為:pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);

當(dāng)用戶(hù)使用系統(tǒng)提供的庫(kù)函數(shù)進(jìn)行進(jìn)程編程,用戶(hù)可以動(dòng)態(tài)地創(chuàng)建進(jìn)程,進(jìn)程之間還有等待,互斥等操作,這些操作都是由linux內(nèi)核來(lái)實(shí)現(xiàn)的。linux內(nèi)核通過(guò)進(jìn)程管理子系統(tǒng)實(shí)現(xiàn)了進(jìn)程有關(guān)的操作,在linux系統(tǒng)上,所有的計(jì)算工作都是通過(guò)進(jìn)程表現(xiàn)的,進(jìn)程可以是短期的(執(zhí)行一個(gè)命令),也可以是長(zhǎng)期的(一種網(wǎng)絡(luò)服務(wù))。linux系統(tǒng)是一種動(dòng)態(tài)系統(tǒng),通過(guò)進(jìn)程管理能夠適應(yīng)不斷變化的計(jì)算需求。

在用戶(hù)空間,進(jìn)程是由進(jìn)程標(biāo)示符(PID)表示的。從用戶(hù)角度看,一個(gè)PID是一個(gè)數(shù)字值,可以唯一標(biāo)識(shí)一個(gè)進(jìn)程,一個(gè)PID值在進(jìn)程的整個(gè)生命周期中不會(huì)更改,但是PID可以在進(jìn)程銷(xiāo)毀后被重新使用。創(chuàng)建進(jìn)程可以使用幾種方式,可以創(chuàng)建一個(gè)新的進(jìn)程,也可以創(chuàng)建當(dāng)前進(jìn)程的子進(jìn)程。

在linux內(nèi)核空間,每個(gè)進(jìn)程都有一個(gè)獨(dú)立的數(shù)據(jù)結(jié)構(gòu),用來(lái)保存該進(jìn)程的ID、優(yōu)先級(jí)、地址的空間等信息,這個(gè)結(jié)構(gòu)也被稱(chēng)做進(jìn)程控制塊(Process Control Block)。所謂的進(jìn)程管理就是對(duì)進(jìn)程控制塊的管理。
linux的進(jìn)程是通過(guò)fork()函數(shù)系統(tǒng)調(diào)用產(chǎn)生的。調(diào)用fork()的進(jìn)程叫做父進(jìn)程,生成的進(jìn)程叫做子進(jìn)程。子進(jìn)程被創(chuàng)建的時(shí)候,除了進(jìn)程ID外,其它數(shù)據(jù)結(jié)構(gòu)與父進(jìn)程完全一致。在fork()系統(tǒng)調(diào)用創(chuàng)建內(nèi)存之后,子進(jìn)程馬上被加入內(nèi)核的進(jìn)程調(diào)試隊(duì)列,然后使用exec()系統(tǒng)調(diào)用,把程序的代碼加入到子進(jìn)程的地址空間,之后子進(jìn)程就開(kāi)始執(zhí)行自己的代碼。

在一個(gè)系統(tǒng)上可以有多個(gè)進(jìn)程,但是一般情況下只有一個(gè)CPU,在同一個(gè)時(shí)刻只能有一個(gè)進(jìn)程在工作,即使有多個(gè)CPU,也不可能和進(jìn)程的數(shù)量一樣多。如果讓若干的進(jìn)程都能在CPU上工作,這就是進(jìn)程管理子系統(tǒng)的工作。linux內(nèi)核設(shè)計(jì)了存放進(jìn)程隊(duì)列的結(jié)構(gòu),在一個(gè)系統(tǒng)上會(huì)有若干隊(duì)列,分別存放不同狀態(tài)的進(jìn)程。一個(gè)進(jìn)程可以有若干狀態(tài),具體是由操作系統(tǒng)來(lái)定義的,但是至少包含運(yùn)行態(tài)、就緒態(tài)和等待3種狀態(tài),內(nèi)核設(shè)計(jì)了對(duì)應(yīng)的隊(duì)列存放對(duì)應(yīng)狀態(tài)的進(jìn)程控制塊。

當(dāng)一個(gè)用戶(hù)進(jìn)程被加載后,會(huì)進(jìn)入就緒態(tài),被加入到就緒態(tài)隊(duì)列,CPU時(shí)間被輪轉(zhuǎn)到就緒態(tài)隊(duì)列后,切換到進(jìn)程的代碼,進(jìn)程被執(zhí)行,當(dāng)進(jìn)程的時(shí)間片到了以后被換出。如果進(jìn)程發(fā)生I/O操作也會(huì)被提前被換出,并且存放到等待隊(duì)列,當(dāng)I/O請(qǐng)求返回后,進(jìn)程又被放入就緒隊(duì)列。linux系統(tǒng)對(duì)進(jìn)程隊(duì)列的管理設(shè)計(jì)了若干不同的方法,主要的目的是提高進(jìn)程調(diào)試的穩(wěn)定性。

2. 內(nèi)存管理

內(nèi)存管理的主要作用是控制多個(gè)進(jìn)程安全地共享主內(nèi)存區(qū)域。當(dāng)CPU提供內(nèi)存管理單元(MMU)時(shí),Linux內(nèi)存管理完成為每個(gè)進(jìn)程進(jìn)行虛擬內(nèi)存到物理內(nèi)存的轉(zhuǎn)換。Linux 2.6引入了對(duì)無(wú)MMU CPU的支持。

使用虛擬內(nèi)存技術(shù)的計(jì)算機(jī),內(nèi)存管理的硬件按照分頁(yè)方式管理內(nèi)存。分頁(yè)方式是把計(jì)算機(jī)系統(tǒng)的物理內(nèi)存按照相同大小等分,每個(gè)內(nèi)存分片稱(chēng)作內(nèi)存頁(yè),通常內(nèi)存頁(yè)大小是4KB。Linux內(nèi)核的內(nèi)存管理子系統(tǒng)管理虛擬內(nèi)存與物理內(nèi)存之間的映射關(guān)系,以及系統(tǒng)可用內(nèi)存空間。內(nèi)存管理要管理的不僅是4KB緩沖區(qū)。Linux提供了對(duì)4KB緩沖區(qū)的抽象,例如slab分配器。這種內(nèi)存管理模式使用4KB緩沖區(qū)為基數(shù),然后從中分配結(jié)構(gòu),并跟蹤內(nèi)存頁(yè)使用情況,比如哪些內(nèi)存頁(yè)是滿(mǎn)的,哪些頁(yè)面沒(méi)有完全使用,哪些頁(yè)面為空。這樣就允許該模式根據(jù)系統(tǒng)需要來(lái)動(dòng)態(tài)調(diào)整內(nèi)存使用。

在支持多用戶(hù)的系統(tǒng)上,由于內(nèi)存占用的增大,容易出現(xiàn)物理內(nèi)存被消耗盡的情況。為了解決物理內(nèi)存被耗盡的問(wèn)題,內(nèi)存管理子系統(tǒng)規(guī)定頁(yè)面可以移出內(nèi)存并放入磁盤(pán)中,這個(gè)過(guò)程稱(chēng)為交換。內(nèi)存管理的源代碼可以在./linux/mm中找到。

3. 虛擬文件系統(tǒng)

Linux虛擬文件系統(tǒng)(VFS)隱藏各種了硬件的具體細(xì)節(jié),為所有的設(shè)備提供了統(tǒng)一的接口。而且,它獨(dú)立于各個(gè)具體的文件系統(tǒng),是對(duì)各種文件系統(tǒng)的一個(gè)抽象,它使用超級(jí)塊super block存放文件系統(tǒng)相關(guān)信息,使用索引節(jié)點(diǎn)inode存放文件的物理信息,使用目錄項(xiàng)dentry存放文件的邏輯信息。

Linux文件系統(tǒng)

在不同格式的文件分區(qū)上,程序都可以正確地讀寫(xiě)文件,并且結(jié)果是一樣的。有時(shí)在使用linux系統(tǒng)的時(shí)候發(fā)現(xiàn),可以在不同類(lèi)型的文件分區(qū)內(nèi)直接復(fù)制文件,對(duì)應(yīng)用程序來(lái)說(shuō),并不知道文件系統(tǒng)的類(lèi)型,甚至不知道文件的類(lèi)型,這就是虛擬文件系統(tǒng)在背后做的工作。虛擬文件系統(tǒng)屏蔽了不同文件系統(tǒng)間的差異,向用戶(hù)提供了統(tǒng)一的接口。

虛擬文件系統(tǒng),即VFS(Virtual File System)是Linux內(nèi)核中的一個(gè)軟件抽象層。它通過(guò)一些數(shù)據(jù)結(jié)構(gòu)及其方法向?qū)嶋H的文件系統(tǒng)如ext2,vfat等提供接口機(jī)制。通過(guò)使用同一套文件 I/O 系統(tǒng)調(diào)用即可對(duì)Linux中的任意文件進(jìn)行操作而無(wú)需考慮其所在的具體文件系統(tǒng)格式;更進(jìn)一步,文件操作可以在不同文件系統(tǒng)之間進(jìn)行。在linux系統(tǒng)中,一切都可以被看做是文件。不僅普通的文本文件、目錄可以當(dāng)做文件進(jìn)行處理,而且字符設(shè)備、塊設(shè)備、套接字等都可以被當(dāng)做文件進(jìn)行處理。這些文件雖然類(lèi)型不同,但是卻使用同一種操作方法。這也是UNIX/Linux設(shè)計(jì)的基本哲學(xué)之一。

虛擬文件系統(tǒng)(簡(jiǎn)稱(chēng)VFS)是實(shí)現(xiàn)“一切都是文件”特性的關(guān)鍵,是Linux內(nèi)核的一個(gè)軟件層,向用戶(hù)空間的程序提供文件系統(tǒng)接口;同時(shí)提供了內(nèi)核中的一個(gè)抽象功能,允許不同類(lèi)型的文件系統(tǒng)存在。VFS可以被理解為一種抽象的接口標(biāo)準(zhǔn),系統(tǒng)中所有的文件系統(tǒng)不僅依靠VFS共存,也依靠VFS協(xié)同工作。為了能夠支持不同的文件系統(tǒng),VFS定義了所有文件系統(tǒng)都支持的、最基本的一個(gè)概念上的接口和數(shù)據(jù)結(jié)構(gòu),在實(shí)現(xiàn)一個(gè)具體的文件系統(tǒng)的時(shí)候,需要向VFS提供符合VFS標(biāo)準(zhǔn)的接口和數(shù)據(jù)結(jié)構(gòu),不同的文件系統(tǒng)可能在實(shí)體概念上有差別,但是使用VFS接口時(shí)需要和VFS定義的概念保持一致,只有這樣,才能實(shí)現(xiàn)對(duì)用戶(hù)的文件系統(tǒng)無(wú)關(guān)性。VFS隱藏了具體文件系統(tǒng)的操作細(xì)節(jié),所以,在VFS這一層以及內(nèi)核其他部分看來(lái),所有的文件系統(tǒng)都是相同的。對(duì)文件系統(tǒng)訪問(wèn)的系統(tǒng)調(diào)用通過(guò)VFS軟件層處理,VFS根據(jù)訪問(wèn)的請(qǐng)求調(diào)用不同的文件系統(tǒng)驅(qū)動(dòng)的函數(shù)處理用戶(hù)的請(qǐng)求。文件系統(tǒng)的代碼在訪問(wèn)物理設(shè)備的時(shí)候,需要使用物理設(shè)備驅(qū)動(dòng)訪問(wèn)真正的硬件。

4. 網(wǎng)絡(luò)接口

網(wǎng)絡(luò)接口提供了對(duì)各種網(wǎng)絡(luò)標(biāo)準(zhǔn)的存取和各種網(wǎng)絡(luò)硬件的支持。如下圖5所示,在Linux中網(wǎng)絡(luò)接口可分為網(wǎng)絡(luò)協(xié)議和網(wǎng)絡(luò)驅(qū)動(dòng)程序,網(wǎng)絡(luò)協(xié)議部分負(fù)責(zé)實(shí)現(xiàn)每一種可能的網(wǎng)絡(luò)傳輸協(xié)議,網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)程序負(fù)責(zé)與硬件設(shè)備通信,每一種可能的硬件設(shè)備都有相應(yīng)的設(shè)備驅(qū)動(dòng)程序。

寫(xiě)網(wǎng)絡(luò)應(yīng)用程序,使用socket通過(guò)TCP/IP協(xié)議與其他機(jī)器通信,和前面介紹的內(nèi)核子系統(tǒng)相似,socket相關(guān)的函數(shù)也是通過(guò)內(nèi)核的子系統(tǒng)完成的,擔(dān)當(dāng)這部分任務(wù)的是內(nèi)核的網(wǎng)絡(luò)子系統(tǒng),有時(shí)也把這部分代碼稱(chēng)為“網(wǎng)絡(luò)堆棧”。Linux內(nèi)核提供了優(yōu)秀的網(wǎng)絡(luò)處理能力和功能,這與網(wǎng)絡(luò)堆棧代碼的設(shè)計(jì)思想是分不開(kāi)的,Linux的網(wǎng)絡(luò)堆棧部分沿襲了傳統(tǒng)的層次結(jié)構(gòu),網(wǎng)絡(luò)數(shù)據(jù)從用戶(hù)進(jìn)程到達(dá)實(shí)際的網(wǎng)絡(luò)設(shè)備需要四個(gè)層次:用戶(hù)進(jìn)程,套接字,網(wǎng)絡(luò)協(xié)議,網(wǎng)絡(luò)設(shè)備。

實(shí)際上,在每層里面還可以分為好多層次,數(shù)據(jù)傳輸?shù)穆窂绞前凑諏哟蝸?lái)的,不能跨越某個(gè)層次。linux網(wǎng)絡(luò)子系統(tǒng)對(duì)網(wǎng)絡(luò)層次采用了類(lèi)似面向?qū)ο蟮脑O(shè)計(jì)思路,把需要處理的層次抽象為不同的實(shí)體,并且定義了實(shí)體之間的關(guān)系和數(shù)據(jù)處理流程:

  1. 網(wǎng)絡(luò)協(xié)議:網(wǎng)絡(luò)協(xié)議可以理解為一種語(yǔ)言,用于網(wǎng)絡(luò)中不同設(shè)備之間的通信,是一種通信的規(guī)范。
  2. 套接字:套接字是內(nèi)核與用戶(hù)程序的接口,一個(gè)套接字對(duì)應(yīng)一個(gè)數(shù)據(jù)連接,并且向用戶(hù)提供了文件I/O,用戶(hù)可以像操作文件一樣在數(shù)據(jù)連接上收發(fā)數(shù)據(jù),具體的協(xié)議處理由網(wǎng)絡(luò)協(xié)議部分處理。套接字是用戶(hù)使用網(wǎng)絡(luò)的接口。
  3. 設(shè)備接口:設(shè)備接口是網(wǎng)絡(luò)子系統(tǒng)中軟件和硬件的接口,用戶(hù)的數(shù)據(jù)最終是需要通過(guò)網(wǎng)絡(luò)硬件設(shè)備發(fā)送和接收的,網(wǎng)絡(luò)設(shè)備千差萬(wàn)別,設(shè)備驅(qū)動(dòng)也不盡相同,通過(guò)設(shè)備接口屏蔽了具體設(shè)備驅(qū)動(dòng)的差異。
  4. 網(wǎng)絡(luò)緩沖區(qū):網(wǎng)絡(luò)緩沖區(qū)也稱(chēng)為套接字緩沖區(qū)(sk_buff),是網(wǎng)絡(luò)子系統(tǒng)中的一個(gè)重要結(jié)構(gòu)。網(wǎng)絡(luò)傳輸數(shù)據(jù)存在許多不定因素,除了物理設(shè)備對(duì)傳輸數(shù)據(jù)的限制(例如MMU),網(wǎng)絡(luò)受到干擾、丟包、重傳等,都會(huì)造成數(shù)據(jù)的不穩(wěn)定,網(wǎng)絡(luò)緩沖區(qū)通過(guò)對(duì)網(wǎng)絡(luò)數(shù)據(jù)的重新整理,使業(yè)務(wù)處理的數(shù)據(jù)包是完整的。網(wǎng)絡(luò)緩沖區(qū)是內(nèi)存中的一塊緩沖區(qū),是網(wǎng)絡(luò)系統(tǒng)與內(nèi)存管理的接口。

5. 進(jìn)程間通信

進(jìn)程通信支持提供進(jìn)程之間的通信,Linux支持進(jìn)程間的多種通信機(jī)制,包含信號(hào)量、共享內(nèi)存、管道等,這些機(jī)制可協(xié)助多個(gè)進(jìn)程、多資源的互斥訪問(wèn)、進(jìn)程間的同步和消息傳遞。

子系統(tǒng)之間的依賴(lài)關(guān)系:
Linux內(nèi)核的5個(gè)組成部分之間的依賴(lài)關(guān)系如下:

  1. 進(jìn)程調(diào)度與內(nèi)存管理之間的關(guān)系:這兩個(gè)子系統(tǒng)互相依賴(lài)。在多道程序環(huán)境下,程序要運(yùn)行必須為之創(chuàng)建進(jìn)程,而創(chuàng)建進(jìn)程的第一件事情,就是將程序和數(shù)據(jù)裝入內(nèi)存。
  2. 進(jìn)程間通信與內(nèi)存管理的關(guān)系:進(jìn)程間通信子系統(tǒng)要依賴(lài)內(nèi)存管理支持共享內(nèi)存通信機(jī)制,這種機(jī)制允許兩個(gè)進(jìn)程除了擁有自己的私有空間,還可以存取共同的內(nèi)存區(qū)域。
  3. 虛擬文件系統(tǒng)與網(wǎng)絡(luò)接口之間的關(guān)系:虛擬文件系統(tǒng)利用網(wǎng)絡(luò)接口支持網(wǎng)絡(luò)文件系統(tǒng)(NFS),也利用內(nèi)存管理支持RAMDISK設(shè)備。
  4. 內(nèi)存管理與虛擬文件系統(tǒng)之間的關(guān)系:內(nèi)存管理利用虛擬文件系統(tǒng)支持交換,交換進(jìn)程(swapd)定期由調(diào)度程序調(diào)度,這也是內(nèi)存管理依賴(lài)于進(jìn)程調(diào)度的惟一原因。當(dāng)一個(gè)進(jìn)程存取的內(nèi)存映射被換出時(shí),內(nèi)存管理向文件系統(tǒng)發(fā)出請(qǐng)求,同時(shí),掛起當(dāng)前正在運(yùn)行的進(jìn)程。

除了這些依賴(lài)關(guān)系外,內(nèi)核中的所有子系統(tǒng)還要依賴(lài)于一些共同的資源。這些資源包括所有子系統(tǒng)都用到的例程,如分配和釋放內(nèi)存空間的函數(shù)、打印警告或錯(cuò)誤信息的函數(shù)及系統(tǒng)提供的調(diào)試?yán)痰取?/p>



Linux中的物理內(nèi)存可以分為以下的部分:內(nèi)核占用內(nèi)存開(kāi)始部分;接下來(lái)是共硬盤(pán),軟盤(pán)使用的高速緩沖區(qū)部分,其中扣除顯存和bios的640k到1m;然后是虛擬盤(pán);最后一部分是為所有程序可以使用的主內(nèi)存區(qū)。

關(guān)于Linux進(jìn)程

進(jìn)程可以在內(nèi)核態(tài)或者用戶(hù)態(tài)運(yùn)行,當(dāng)資源可用就被喚醒,進(jìn)入就緒態(tài);當(dāng)進(jìn)程處于可中斷睡眠狀態(tài),收到信號(hào)可被喚醒;當(dāng)處于不可中斷睡眠狀態(tài),只能被使用wakeup等的喚醒;當(dāng)進(jìn)程處于暫停狀態(tài),可發(fā)送信號(hào)使其進(jìn)入就緒態(tài);當(dāng)僵死狀態(tài),當(dāng)已經(jīng)停止運(yùn)行,父進(jìn)程還沒(méi)有調(diào)用wait查詢(xún)狀態(tài),一旦父進(jìn)程調(diào)用完wait取得子進(jìn)程信息后,這個(gè)進(jìn)程任務(wù)數(shù)據(jù)結(jié)構(gòu)就會(huì)被釋放掉。



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,663評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,125評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 175,506評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,614評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,402評(píng)論 6 404
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 54,934評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,021評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,168評(píng)論 0 287
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,690評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,596評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,784評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,288評(píng)論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,027評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,404評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,662評(píng)論 1 280
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,398評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,743評(píng)論 2 370

推薦閱讀更多精彩內(nèi)容