臺前幕后!從技術上解析Linux內核是如何工作的顷蟆,對于嵌入式Linux開發(fā)者有所幫助

姓名:袁永輝? ? ? 學號:17101223423

轉載自:http://mp.weixin.qq.com/s/alw97AsG5tSH8MEoAaMKvg

【嵌牛導讀】:knerne對Linux來說是最重要的一部分诫隅,廣義地來說kernel就是一個軟件,它在硬件和運行在計算機上的應用程序之間提供了一個層帐偎。

【嵌牛鼻子】:嵌入式逐纬; Linux ;內核

【嵌牛提問】:Linux 內核的工作原理是怎樣的削樊?

【嵌牛正文】:

牛津字典中對"kernel"一詞的定義是:"較軟的豁生、通常是一個堅果可食用的部分。"當然還有第二種定義:"某個東西核心或者最重要的部分漫贞。"對Linux來說甸箱,它的Kernel無疑屬于第二種解釋。讓我們來看看這個重要的東西是如何工作的绕辖,先從一點理論說起摇肌。

廣義地來說kernel就是一個軟件擂红,它在硬件和運行在計算機上的應用程序之間提供了一個層仪际。嚴格點從計算機科學的角度來說,Linux中的Kernel指的是Linus Torvalds在90年代初期寫的那點代碼昵骤。

所有的你在Linux各版本中看到的其他東西--Bash shell树碱、KDE窗口管理器、web瀏覽器变秦、X服務器成榜、Tux Racer以及所有的其他,都不過是運行在Linux上的應用而已蹦玫,而不是操作系統(tǒng)自身的一部分赎婚。為了給大家一個更加直觀的感覺,我來舉個例子樱溉,比如RHEL5的安裝大概要占據(jù)2.5GB的硬盤空間(具體多大當然視你的選擇安裝來定)挣输,在這其中,kernel以及它的各個模塊組件福贞,只有47MB撩嚼,所占 比例約為2%。

在kernel內部

那么kernel到底是如何工作的呢?如下面的圖表。Kernel通過許多的進入端口也就是我們從技術角度所說的系統(tǒng)調用完丽,來使得運行在它上面的應用程序可用恋技。Kernel使用的系統(tǒng)調用比如"讀"和"寫"來提供你硬件的抽象(abstraction)。

圖片發(fā)自簡書App

從程序員的視角來看逻族,這些看起來只是普通的功能調用蜻底,然而實際上系統(tǒng)調用在處理器的操作模式上,從用戶空間到Kernel空間有一個明顯的切換瓷耙。同時朱躺,系統(tǒng)調用提供了一個"Linux虛擬機",可以被認為是對硬件的抽象搁痛。

Kernel提供的更明顯的抽象之一是文件系統(tǒng)长搀。舉例來說,這里有一段短的程序是用C寫的鸡典,它打開了一個文件并將內容拷貝到標準的輸出:

#include <fcntl.h>

int main()

{

? ? int fd, count; char buf[1000];

? ? fd=open("mydata", O_RDONLY);

? ? count = read(fd, buf, 1000);

? ? write(1, buf, count);

? ? close(fd);

}

在這里源请,你可以看到四個系統(tǒng)調用的例子:打開、讀彻况、寫和關閉谁尸。不談這段程序語法的細節(jié),重點是:通過這些系統(tǒng)調用Linux Kernel提供了一個文件的"錯覺"纽甘,而實際上它不過是一堆數(shù)據(jù)有了個名字良蛮,這樣一來你就不必去與硬件底層的堆棧、分區(qū)悍赢、頭和指針决瞳、分區(qū)等交涉了,而是 直接以例子中的方式與硬件"交流"左权,這也就是我們所說的抽象(abstraction)皮胡,將底層的東西以更易懂的方式表達出來。

臺前幕后

系統(tǒng)文件是Kernel提供的較為明顯的一種抽象赏迟。還有一些特性不是這么的明顯屡贺,比如進程調度。任何一個時間锌杀,都可能有好幾個進程或者程序等待著運行甩栈。Kernel的時間調度給每個進程分配CPU時間,所以就一段時間內來說糕再,我們會有種錯覺:電腦同一時間運行好幾個程序量没。這是另外一個C程序:

#include <stdlib.h>

main()

{

? if (fork()) {

? ? write(1, "Parent/n", 7);

? ? wait(0);

? ? exit(0);

? }

? else {

? ? write(1, "Child/n", 6);

? ? exit(0);

? }

}

在這個程序中創(chuàng)建了一個新進程,而原來的進程(父進程)和新進程(子進程)都編寫了標準輸出然后結束亿鲜。注意系統(tǒng)調用fork(), exit() 以及 wait()執(zhí)行程序的創(chuàng)建允蜈、結束和各自同步冤吨。這是進程管理和調度中最典型的簡單調用。

Kernel還有一個更加不易見到的功能饶套,連程序員都不易察覺漩蟆,那就是存儲管理。每個程序運行得都好像它有個自己的地址空間來調用一樣妓蛮,實際上它跟其他進 程一樣共享計算機的物理存儲怠李,如果系統(tǒng)運行的存儲過低,它的地址空間甚至會被磁盤的交互區(qū)暫時寄用蛤克。存儲管理的另外一個方面是防止一個進程訪問其他進程的 地址空間--對于多進程操作系統(tǒng)來說這是很必要的一個防范措施捺癞。

Kernel同樣還配置網(wǎng)絡鏈接協(xié)議比如IP、TCP和UDP等构挤,它們在網(wǎng)絡上提供機器對機器(machine-to-machine)和進程對進程 (process-to-process)的通信髓介。這里又會造成一種假象,即TCP在兩個進程之間提供了一個固定連接--就好像連接兩個電話的銅線一樣筋现, 實際中卻并沒有固定的連接唐础,特殊的引用協(xié)議比如FTP、DNS和HTTP是通過用戶級程序來實施的矾飞,而并非Kernel的一部分一膨。

Linux(像之前的Unix)在安全方面口碑很好,這是因為Kernel跟蹤記錄了每個運行進程的user ID和group ID洒沦,每次當一個應用企圖訪問資源(比如打開一個文件來寫入)的時候豹绪,Kernel就會核對文件上的訪問許可然后做出允許/禁止的命令。這種訪問控制模式 最終對整個Linux系統(tǒng)的安全作用很大申眼。

Kernel還提供了一大套模塊的集合瞒津,其功能包括如何處理與硬件設備交流的諸多細節(jié)、如何從磁盤讀取一個分區(qū)豺型、如果從網(wǎng)絡接口卡獲取數(shù)據(jù)包等仲智。有時我們稱這些為設備驅動买乃。

模塊化的Kernel

現(xiàn)在我們隊Kernel是做什么的已經(jīng)有了一些了解姻氨,讓我們再來簡單看下它的物理組成。早期版本的Linux Kernel是整體式的剪验,也就是說所有的部件都靜態(tài)地連接成一個(很大的)執(zhí)行文件肴焊。

相比較而言,現(xiàn)在的Linux Kernel是模塊化的:許多功能包含在模塊內功戚,然后動態(tài)地載入kernel中娶眷。這使得kernel的內核很小,而且在運行kernel時可以不必reboot就能載入和替代模塊啸臀。

Kernel的內核在boot time時從位于/boot 目錄的一個文件加載進存儲中届宠,通常這個/boot目錄會被叫做KERNELVERSION烁落,KERNELVERSION與kernel版本有關。(如果你想知道你的kernel版本是什么豌注,運行命令行顯 示系統(tǒng)信息-r伤塌。)kernel的模塊位于目錄/lib/modules/KERNELVERSION之下,所有的組件都會在kernel安裝時被拷貝轧铁。

管理模塊

大部分情況下每聪,Linux管理它的模塊不需要你的幫忙,但是如果必要的時候有命令行可以來手動檢查和管理模塊齿风。比如药薯,為了查清楚當前到底哪個模塊在載入kernel。這里有一個輸出的例子:

# lsmod

pcspkr? ? ? ? ? ? ? 4224? 0

hci_usb? ? ? ? ? ? 18204? 2

psmouse? ? ? ? ? ? 38920? 0

bluetooth? ? ? ? ? 55908? 7 rfcomm,l2cap,hci_usb

yenta_socket? ? ? 27532? 5

rsrc_nonstatic? ? 14080? 1 yenta_socket

isofs? ? ? ? ? ? ? 36284? 0

輸出的內容包括:模塊的名字救斑、大小童本、使用次數(shù)和依賴于它的模塊列表。使用次數(shù)對防止卸載當前活躍的模塊非沉澈颍總要巾陕。Linux只允許使用次數(shù)為零的模塊被移除。

你可以使用modprobe來手動加載和卸載模塊纪他,(還有兩個命令行叫做insmod和rmmod鄙煤,但modprobe更易于使用因為它自動移除了模塊依 賴)。比如lsmod的輸出在我們的電腦上顯示了一個名叫isofs的卸載模塊茶袒,它的使用次數(shù)是零而且沒有依賴模塊梯刚,(isofs是一個模塊,它支持CD上使用的ISO系統(tǒng)文件格式)這種情況下薪寓,kernel會允許我們卸載模塊:

# modprobe -r isofs

現(xiàn)在亡资,isofs不再顯示在Ismod的輸出中,kernel由此節(jié)省了36,284字節(jié)的存儲向叉。如果你放入CD并且讓它自動安裝锥腻,kernel將自動重 新載入isofs模塊,而且isofs的使用次數(shù)增加到1次母谎。如果這時候你還試圖移除模塊瘦黑,就不會成功了因為它正在被使用:

# modprobe -r isofs

FATAL: Module isofs is in use.

Lsmod只是列出了當前被載入的模塊,modprobe則將列出所有可用的模塊奇唤,它實際上輸出了/lib/modules/KERNELVERSION目錄下所有的模塊幸斥,名單會很長!

實際上咬扇,使用modprobe來手動加載一個模塊并不常見甲葬,但確實可以通過modprobe命令行來對模塊設置參數(shù),例如:

# modprobe usbcore blinkenlights=1

我們并不是在創(chuàng)建blinkenlights懈贺,而是usbcore模塊的實參數(shù)经窖。

那么如何知道一個模塊會接受什么參數(shù)呢坡垫?一個比較好的方法是使用modinfo命令,它列出了關于模塊的種種信息画侣。這里有一個關于模塊snd-hda-intel的例子

# modinfo snd-hda-intel

filename:? ? ? /lib/modules/2.6.20-16-generic/kernel/sound/pci/hda/snd-hda-intel.ko

description:? ? Intel HDA driver

license:? ? ? ? GPL

srcversion:? ? A3552B2DF3A932D88FFC00C

alias:? ? ? ? ? pci:v000010DEd0000055Dsv*sd*bc*sc*i*

alias:? ? ? ? ? pci:v000010DEd0000055Csv*sd*bc*sc*i*

depends:? ? ? ? snd-pcm,snd-page-alloc,snd-hda-codec,snd

vermagic:? ? ? 2.6.20-16-generic SMP mod_unload 586

parm:? ? ? ? ? index:Index value for Intel HD audio interface. (int)

parm:? ? ? ? ? id:ID string for Intel HD audio interface. (charp)

parm:? ? ? ? ? model:Use the given board model. (charp)

parm:? ? ? ? ? position_fix:Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size). (int)

parm:? ? ? ? ? probe_mask:Bitmask to probe codecs (default = -1). (int)

parm:? ? ? ? ? single_cmd:Use single command to communicate with codecs (for debugging only). (bool)

parm:? ? ? ? ? enable_msi:Enable Message Signaled Interrupt (MSI) (int)

parm:? ? ? ? ? enable:bool

對我們來說比較有興趣的以"parm"開頭的那些部分:顯示了模塊所接受的參數(shù)葛虐。這些描述都比較簡明,如果想要更多的信息棉钧,那就安裝kernel的源代碼屿脐,在類似于/usr/src/KERNELVERSION/Documentation的目錄下你會找到。

里面會有一些有趣的東西宪卿,比如文件/usr/src/KERNELVERSION/Documentation/sound/alsa/ALSA-Configuration.txt描述的是被許多ALSA聲音模塊承認的參數(shù)的诵;/usr/src/KERNELVERSION /Documentation/kernel-parameters.txt這個文件也很有用。

前幾天在Ubuntu論壇有一個例子佑钾,說的是如何將參數(shù)傳遞到一個模塊(詳見https://help.ubuntu.com/community /HdaIntelSoundHowto)西疤。實際上問題的關鍵是snd-hda-intel參數(shù)在正確驅動聲音硬件時需要一點操作,而且在boot time加載時會中止休溶。解決方法的一部分是將probe_mask=1選項賦給模塊代赁,如果你是手動加載模塊,你需要輸入:

# modprobe snd-hda-intel probe_mask=1

更有可能兽掰,你在文件/etc/modprobe.conf中放置這樣類似的一行:options snd-hda-intel probe_mask=1

這"告訴"modprobe每次在加載snd-hda-intel模塊時包含probe_mask=1選項“虐現(xiàn)在的有些Linux版本將這一信息分離進/etc/modprobe.d下的不同文件中了杉女,而不是放入modprobe.conf中。

/proc系統(tǒng)文件

Linux kernel同樣通過/proc系統(tǒng)文件來展示了許多細節(jié)速勇。為了說明/proc烦磁,我們首先需要擴展我們對于文件的理解个初。除了認為文件就是存儲在硬盤或者CD或者存儲空間上的持久信息之外,我們還應當把它理解為任何可以通過傳統(tǒng)系統(tǒng)調用如:打開磅轻、讀谆膳、寫漱病、關閉等訪問的信息,當然它也可以被常見的程序訪問注盈。

/proc之下的"文件"完全是kernel虛擬的一個部分老客,給我們一個視角可以看到kernel內部的數(shù)據(jù)結構。實際上朴则,許多Linux的報告工具均能 夠很好地呈現(xiàn)在/proc下的文件中尋到的格式化版本的信息乌妒。比如,一列/proc/modules將展示一列當前加載的模塊侦啸。

同樣的光涂,/proc/meminfo提供了關于虛擬存儲系統(tǒng)當前狀態(tài)的更多細節(jié)信息,而類如vmstat的工具則是以一種更加可理解的方式提供了相同的一 些信息齐佳;/proc/net/arp顯示了系統(tǒng)ARP cache的當前內容本鸣,從命令行來說,arp -a顯示的也是相同的信息命爬。

尤其有意思的是/proc/sys下的"文件"。/proc/sys/net/ipv4/ip_forward下的設置告訴我們kernel是否將轉發(fā)IP數(shù)據(jù)包艇抠,也就是說是否扮演網(wǎng)關的作用。現(xiàn)在,kernel告訴我們這是關閉的:

# cat /proc/sys/net/ipv4/ip_forward

0

當你發(fā)現(xiàn)你可以對這些文件寫入的時候青伤,你會覺得更加有意思。繼續(xù)舉例來說:

# echo 1 > /proc/sys/net/ipv4/ip_forward

將在運行的kernel中打開IP 轉發(fā)(IP forwarding)

除了使用cat和echo來檢查和更正/proc/sys下的設置以外,你也可以使用sysctl命令:

# sysctl net.ipv4.ip_forward

net.ipv4.ip_forward = 0

這等同于:

# cat /proc/sys/net/ipv4/ip_forward

0

也等同于:

# sysctl -w net.ipv4.ip_forward=1

net.ipv4.ip_forward = 1

還等同于:

# echo 1 > /proc/sys/net/ipv4/ip_forward

需要注意的是,以這種方式你所做的設置改變只能影響當前運行的kernel的,當reboot的時候就不再有效。如果想讓設置永久有效宵蕉,將它們放置在/etc/sysctl.conf文件中酝静。在boot time時,sysctl將自動重新確定它在此文件下找到的任何設置宗苍。

/etc/sysctl.conf下的代碼行大概是這樣的:net.ipv4.ip_forward=1

性能調優(yōu)(performance tuning)

有這樣一個說法:/proc/sys下可寫入的參數(shù)孕育了整個Linux性能調優(yōu)的亞文化让歼。我個人覺得這種說法有點過夸补箍,但這里會有幾個你確實很想一試的 例子:Oracle 10g的安裝說明(www.oracle.com/technology/obe/obe10gdb/install/linuxpreinst /linuxpreinst.htm)要求你設置一組參數(shù)裹粤,包括:kernel.shmmax=2147483648這將公用存儲器的大小設置為2GB遥诉。(公用存儲器是處理期內的通信機制拇泣,允許存儲單元在多個進程的地址空間內同時可用)

IBM 'Redpaper'在Linux性能和調優(yōu)方面的說明(www.redbooks.ibm.com/abstracts/redp4285.html) 在調教/proc/sys下的參數(shù)方面給出了不少建議挫酿,包括:vm.swappiness=100 這個參數(shù)控制著存儲頁如何被交換到磁盤愕难。

一些參數(shù)可以被設置從而提高安全性早龟,如net.ipv4.icmp_echo_ignore_broadcasts=1它"告訴"kernel不必響應ICMP請求,從而使得你的網(wǎng)絡免受類如Smurf攻擊之類的拒絕服務器(denial-of-service)型攻擊猫缭。

net.ipv4.conf.all.rp_filter=1 則是"告訴"kernel加強入站過濾(ingress filtering)和出站過濾(egress filtering)

那么有沒有一個說明能涵蓋這所有的參數(shù)葱弟?好吧,這有一行命令:# sysctl -a它將展示所有的參數(shù)名字和當前值猜丹。列表很長芝加,但是你無法知道這些參數(shù)是做什么的。另外比較有用的參考是Red Hat Enterprise Linux Reference Guide,對此有整章節(jié)的描述藏杖。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末将塑,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蝌麸,更是在濱河造成了極大的恐慌点寥,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件来吩,死亡現(xiàn)場離奇詭異敢辩,居然都是意外死亡,警方通過查閱死者的電腦和手機弟疆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門戚长,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人怠苔,你說我怎么就攤上這事同廉。” “怎么了柑司?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵迫肖,是天一觀的道長。 經(jīng)常有香客問我帜羊,道長咒程,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任讼育,我火速辦了婚禮帐姻,結果婚禮上,老公的妹妹穿的比我還像新娘奶段。我一直安慰自己饥瓷,他們只是感情好,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布痹籍。 她就那樣靜靜地躺著呢铆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蹲缠。 梳的紋絲不亂的頭發(fā)上棺克,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機與錄音线定,去河邊找鬼娜谊。 笑死,一個胖子當著我的面吹牛斤讥,可吹牛的內容都是我干的纱皆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼派草!你這毒婦竟也來了搀缠?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤近迁,失蹤者是張志新(化名)和其女友劉穎艺普,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體钳踊,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡衷敌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年勿侯,在試婚紗的時候發(fā)現(xiàn)自己被綠了拓瞪。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡助琐,死狀恐怖祭埂,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情兵钮,我是刑警寧澤蛆橡,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站掘譬,受9級特大地震影響泰演,放射性物質發(fā)生泄漏。R本人自食惡果不足惜葱轩,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一睦焕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧靴拱,春花似錦垃喊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至偎窘,卻和暖如春乌助,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背陌知。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工他托, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人纵诞。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓上祈,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子登刺,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內容