偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Linux內(nèi)核入門,包教會(huì)

原創(chuàng)
系統(tǒng) Linux
Linux內(nèi)核雖然是一般用戶可學(xué)可不學(xué)的內(nèi)容,但可以說卻是Linux操作系統(tǒng)中最好玩的部分。尤其對(duì)于開發(fā)者而言,Linux內(nèi)核開發(fā)絕對(duì)是最理想的磨練場所。本文將從零開始介紹被視為高深的Linux內(nèi)核,內(nèi)容涉及內(nèi)核源代碼的下載,編譯,安裝,以及內(nèi)核開發(fā)相關(guān)的內(nèi)容。

【51CTO精選譯文】這年頭,Linux成了一個(gè)時(shí)髦詞。自詡對(duì)電腦玩的精通的學(xué)生和IT人士們,沒有哪個(gè)不在自己的電腦上安裝一、兩個(gè)Linux,并自覺趕上了時(shí)髦。然而,在Ubuntu或SUSE的論壇中,經(jīng)常有這樣的對(duì)話:

“你學(xué)Linux學(xué)了這么久,都學(xué)到了什么?”

“哦,我現(xiàn)在Linux的安裝、升級(jí)、桌面美化都很熟練!你看我這是最新版的Ubuntu,桌面很漂亮吧!”

“……”

Linux社區(qū)中有一句名言:如果你進(jìn)入你的操作系統(tǒng)不知道該做什么,那最好還是關(guān)掉電腦,一定有更重要的事等著你去做。說真的,如果對(duì)Linux命令不熟練,真的不能算是學(xué)過Linux。然而另一方面,Linux內(nèi)核雖然是一般用戶可學(xué)可不學(xué)的內(nèi)容,但可以說卻是Linux操作系統(tǒng)中最好玩的部分。尤其對(duì)于開發(fā)者而言,Linux內(nèi)核開發(fā)絕對(duì)是最理想的磨練場所。51CTO編輯一直認(rèn)為,國外之所以IT技術(shù)大拿林立,和他們從小接觸類UNIX系統(tǒng)、把玩內(nèi)核開發(fā)是脫不了關(guān)系的。

下面是Linux內(nèi)核開發(fā)者Robert Love寫的一篇入門文章,號(hào)稱“包教會(huì)”,推薦對(duì)Linux內(nèi)核開發(fā)感興趣的學(xué)生、Linux愛好者、開發(fā)者以及系統(tǒng)管理員們一定不要錯(cuò)過。當(dāng)然,雖然標(biāo)題說是包教會(huì),你可能需要一定的Linux命令以及C語言的基礎(chǔ)。

以下是正文內(nèi)容:

Linux內(nèi)核一直都被視為學(xué)習(xí)Linux最難的一塊,相信大家也一定看過不少關(guān)于內(nèi)核的文章,但捫心自問,你現(xiàn)在究竟掌握了多少?本文將從零開始介紹被視為高深的Linux內(nèi)核,內(nèi)容涉及內(nèi)核源代碼的下載,編譯,安裝,以及內(nèi)核開發(fā)相關(guān)的內(nèi)容。

如何獲取Linux內(nèi)核源代碼

下載Linux內(nèi)核當(dāng)然要去官方網(wǎng)站了,網(wǎng)站提供了兩種文件下載,一種是完整的Linux內(nèi)核,另一種是內(nèi)核增量補(bǔ)丁,它們都是tar歸檔壓縮包。除非你有特別的原因需要使用舊版本的Linux內(nèi)核,否則你應(yīng)該總是升級(jí)到最新版本。

使用Git

由Linus領(lǐng)頭的內(nèi)核開發(fā)隊(duì)伍從幾年前就開始使用Git版本控制系統(tǒng)管理Linux內(nèi)核了(參考閱讀:什么是Git?),而Git項(xiàng)目本身也是由Linus創(chuàng)建的,它和傳統(tǒng)的CVS不一樣,Git是分布式的,因此它的用法和工作流程很多開發(fā)人員可能會(huì)感到很陌生,但我強(qiáng)烈建議使用Git下載和管理Linux內(nèi)核源代碼。

你可以使用下面的Git命令獲取Linus內(nèi)核代碼樹的最新“推送”版本:

$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git

然后使用下面的命令將你的代碼樹與Linus的代碼樹最新狀態(tài)同步:

$ git pull

安裝內(nèi)核源代碼

內(nèi)核包有GNU zip(gzip)和bzip2格式。Bzip2是默認(rèn)和首選格式,因?yàn)樗膲嚎s比通常比gzip更好,bzip2格式的Linux內(nèi)核包一般采用linux-x.y.z.tar.bz2形式的文件名,這里的x.y.z是內(nèi)核源代碼的具體版本號(hào),下載到源代碼包后,解壓和抽取就很簡單了,如果你下載的是bzip2包,運(yùn)行:

$ tar xvjf linux-x.y.z.tar.bz2

如果你下載的是gzip包,則運(yùn)行:

$ tar xvzf linux-x.y.z.tar.gz

無論執(zhí)行上面哪一個(gè)命令,最后都會(huì)將源代碼解壓和抽取到linux-x.y.z目錄下,如果你使用Git下載和管理內(nèi)核源代碼,你不需要下載tar包,只需要運(yùn)行g(shù)it clone命令,它就會(huì)自動(dòng)下載和解壓。

內(nèi)核源代碼通常都會(huì)安裝到/usr/src/linux下,但在開發(fā)的時(shí)候最好不要使用這個(gè)源代碼樹,因?yàn)獒槍?duì)你的C庫編譯的內(nèi)核版本通常也鏈接到這里的。

應(yīng)用補(bǔ)丁

Linux內(nèi)核開發(fā)人員會(huì)將自己的修改做成補(bǔ)丁與其它人員分享,而且補(bǔ)丁是增量的,增量補(bǔ)丁是從一個(gè)內(nèi)核樹移動(dòng)到另一個(gè)內(nèi)核樹的有效方法,不用下載完整的內(nèi)核包就可以升級(jí)內(nèi)核,不僅可節(jié)省帶寬,也節(jié)省了內(nèi)核升級(jí)時(shí)間,應(yīng)用補(bǔ)丁之前先進(jìn)入內(nèi)核源代碼樹所在目錄,然后運(yùn)行:

$ patch –p1 < ../patch-x.y.z

注意,補(bǔ)丁包也有明確的版本號(hào),這里的版本號(hào)與Linux內(nèi)核源代碼的版本號(hào)要一致,內(nèi)核和補(bǔ)丁版本號(hào)不一致時(shí),強(qiáng)制應(yīng)用補(bǔ)丁會(huì)引起意想不到的后果。

內(nèi)核源代碼樹介紹

內(nèi)核源代碼樹分為許多目錄,它們下面又包含許多子目錄,源代碼樹的頂級(jí)目錄及其描述參見下表。

目錄 描述
arch 特定架構(gòu)的源代碼
block 塊I/O層
crypto 加密API
Documentation 內(nèi)核源代碼文檔
drivers 設(shè)備驅(qū)動(dòng)
firmware 使用某個(gè)驅(qū)動(dòng)需要的設(shè)備固件
fs VFS和獨(dú)立文件系統(tǒng)
include 內(nèi)核頭
init 內(nèi)核啟動(dòng)和初始化
ipc 進(jìn)程間通信
kernel 核心子系統(tǒng),如調(diào)度器
lib 助手例行程序
mm 內(nèi)存管理子系統(tǒng)和VM
net 網(wǎng)絡(luò)子系統(tǒng)
samples 示例,示范代碼
scripts 用于生成內(nèi)核的腳本
security Linux安全模塊
sound 聲音子系統(tǒng)
usr 早期的用戶空間代碼(叫做initramfs)
tools 輔助Linux開發(fā)的工具
virt 虛擬化基礎(chǔ)設(shè)施

在源代碼樹的根目錄下還有很多文件需要說明,COPYING是內(nèi)核許可描述文件(即GNU GPL v2),CREDITS是參與Linux內(nèi)核的開發(fā)人員名單,MAINTAINERS列出了維護(hù)各個(gè)子系統(tǒng)和驅(qū)動(dòng)的個(gè)人,Makefile是內(nèi)核Makefile的基礎(chǔ)。

#p#

生成內(nèi)核

生成內(nèi)核其實(shí)很簡單,甚至比編譯和安裝其它系統(tǒng)級(jí)組件,如glibc還要簡單,從2.6版本開始,Linux內(nèi)核引入了一個(gè)新的配置和生成系統(tǒng),它使生產(chǎn)內(nèi)核的操作變得更加簡單了。

配置內(nèi)核

既然已經(jīng)拿到內(nèi)核源代碼,那我們在開始編譯前就可以根據(jù)需要自行配置和定制,可以編譯你指定的功能和想要的驅(qū)動(dòng),配置內(nèi)核是生成內(nèi)核必須的一步,因?yàn)閮?nèi)核提供了大量的功能,支持各種不同的硬件,有很多都需要配置,內(nèi)核配置是由配置選項(xiàng)控制的,配置選項(xiàng)都有CONFIG前綴,例如,對(duì)稱多處理(SMP)是由CONFIG_SMP配置選項(xiàng)配置的,如果設(shè)置了這個(gè)選項(xiàng),SMP就被啟用了,反之則被禁用,配置選項(xiàng)可以確定會(huì)生成哪個(gè)文件,也可以通過預(yù)處理指令操控代碼。

配置選項(xiàng)可以控制生成過程要么是布爾型,要么是三態(tài)型,布爾型就是“是”或“否”,大部分內(nèi)核配置選項(xiàng)都屬于布爾型,如CONFIG_PREEMPT,而三態(tài)型則在“是”和“否”的基礎(chǔ)上,又增加一個(gè)“模塊”選項(xiàng),模塊選項(xiàng)表示配置選項(xiàng)被設(shè)置了,但最后會(huì)編譯成模塊,而不是直接編譯進(jìn)內(nèi)核,模塊可以理解為可獨(dú)立動(dòng)態(tài)載入的對(duì)象,一般來說,驅(qū)動(dòng)配置通常都是三態(tài)型。

配置選項(xiàng)也可以是字符串或整數(shù),這樣的選項(xiàng)不會(huì)控制生成過程,指定的值由內(nèi)核源代碼訪問預(yù)處理宏時(shí)使用,例如,可以為某個(gè)配置選項(xiàng)指定靜態(tài)分配數(shù)組的大小。

Linux廠商也會(huì)隨發(fā)行版提供預(yù)編譯的內(nèi)核,如Canonical為Ubuntu,或Red Hat為Fedora提供的內(nèi)核,這樣的內(nèi)核通常只啟用了需要的內(nèi)核功能,幾乎所有驅(qū)動(dòng)都被編譯成模塊了,這樣的內(nèi)核提供了一個(gè)良好的基礎(chǔ)內(nèi)核和廣泛的硬件模塊支持,無論如何,想要成為內(nèi)核高手,你應(yīng)該編譯自己的內(nèi)核。

值得慶幸的是,內(nèi)核提供了很多工具簡化配置 ,最簡單的工具是基于文本命令行的實(shí)用程序,如:

$ make config

這個(gè)工具會(huì)一個(gè)選項(xiàng)一個(gè)選項(xiàng)地配置,但用戶需要參與,如指定“是(y)”,“否(m)”還是“模塊(m)”,整個(gè)配置過程需要很長的時(shí)間,因此,除非是有人按小時(shí)計(jì)費(fèi)請(qǐng)你升級(jí)內(nèi)核,實(shí)在找不出別的理由用這種最原始的方法配置內(nèi)核了,相反,有現(xiàn)成的基于ncurses的圖形化工具可以代替。

$ make menuconfig

或是基于gtk+的圖形化工具

$ make gconfig

上述三個(gè)工具都將配置選項(xiàng)分成多個(gè)類別,如“處理器類型和特征”,你可以在這些類別上來回移動(dòng),查看內(nèi)核選項(xiàng),當(dāng)然也可以修改它們的設(shè)置了。

下面這個(gè)命令會(huì)根據(jù)你的架構(gòu)創(chuàng)建一個(gè)默認(rèn)的配置基礎(chǔ)。

$ make defconfig

雖然默認(rèn)配置有些武斷(在i386上,默認(rèn)配置是由Linus配置的),但如果你從未配置過內(nèi)核,它提供了一個(gè)良好的開端。

配置選項(xiàng)存儲(chǔ)在源代碼樹根目錄下一個(gè)名叫.config的文件中,你可以打開這個(gè)文件手工編輯其中的配置選項(xiàng),修改后或要在新的內(nèi)核源代碼樹上應(yīng)用現(xiàn)有配置文件,你可以使用下面的命令驗(yàn)證和更新配置:

$ make oldconfig

在生成內(nèi)核之前必須運(yùn)行這個(gè)命令。

配置選項(xiàng)CONFIG_IKCONFIG_PROC指定了完整的內(nèi)核配置文件壓縮包位置,默認(rèn)是/proc/config.gz,這樣在生成新內(nèi)核時(shí)要克隆現(xiàn)有的配置就變得非常簡單了。如果你當(dāng)前的內(nèi)核開啟了這個(gè)選項(xiàng),你可以從/proc拷貝該配置文件,然后在此基礎(chǔ)上生成新的內(nèi)核:

$ zcat /proc/config.gz > .config
$ make oldconfig

內(nèi)核配置好后,使用下面的命令進(jìn)行生成:

$ make

和2.6以前的內(nèi)核不一樣,在生成內(nèi)核前不再需要執(zhí)行make dep命令了,依賴樹會(huì)自動(dòng)維護(hù),也不需要再指定特定的生成類型,如bzImage,或獨(dú)立生成模塊,默認(rèn)Makefile規(guī)則會(huì)自動(dòng)處理好一切。

將干擾信息最小化

在生成過程中會(huì)遭到警告和錯(cuò)誤的干擾。最小化干擾信息的一個(gè)訣竅是重定向make的輸出,但仍然會(huì)看到一些警告和錯(cuò)誤:

$ make > ../detritus

如果你想查看生成輸出,你可以事后閱讀這個(gè)文件,如果你完全不想看到任何輸出,那么就重定向到/dev/null:

$ make > /dev/null

同時(shí)執(zhí)行多個(gè)生成作業(yè)

Make命令提供了一個(gè)功能可以將生成過程拆分成多個(gè)平行的作業(yè),這些作業(yè)可以獨(dú)立運(yùn)行,也可以并行運(yùn)行,在多處理器系統(tǒng)上可以極大地提高生成速度,也提高了處理器利用率,因?yàn)樯纱笮驮创a樹會(huì)出現(xiàn)大量的I/O等待時(shí)間。

默認(rèn)情況下,make只能拆分成一個(gè)作業(yè),因?yàn)镸akefiles常常會(huì)包含不正確的依賴信息,如果真是這樣,多個(gè)并行執(zhí)行的作業(yè)將會(huì)引起混亂,最終會(huì)導(dǎo)致生成過程失敗,如果Makefiles中的依賴信息無誤,那么完全可以拆分成多個(gè)作業(yè)執(zhí)行,如:

$ make –jn

這里的n表示拆分的作業(yè)數(shù)量,通常按每個(gè)處理器拆分成1-2個(gè)作業(yè),例如,在一個(gè)16核心的機(jī)器上 ,你可以運(yùn)行:

$ make -j32 > /dev/null

使用distcc或ccache等優(yōu)秀的工具也可以大大提高生成速度。

#p#

安裝新內(nèi)核

內(nèi)核生成好之后,你需要安裝它,如何安裝于系統(tǒng)架構(gòu)和引導(dǎo)加載程序有關(guān),我們以x86架構(gòu),grub引導(dǎo)加載程序?yàn)槔M(jìn)行說明。

首先將arch/i386/boot/bzImage拷貝到/boot,重命名為vmlinuz- version,這里的version也是版本號(hào),然后編輯/boot/grub/grub.conf,為新內(nèi)核添加相應(yīng)的項(xiàng)目,如果是使用LILO引導(dǎo)裝載程序,則修改/etc/lilo.conf文件,然后運(yùn)行l(wèi)ilo。

模塊的安裝與系統(tǒng)架構(gòu)無關(guān),都是自動(dòng)完成的,以root用戶運(yùn)行:

% make modules_install

這個(gè)命令會(huì)將所有編譯好的模塊安裝到/lib/modules下對(duì)應(yīng)的子目錄中。

生成過程會(huì)在源代碼樹根目錄下創(chuàng)建一個(gè)System.map文件,它包含一個(gè)符號(hào)查找表,映射內(nèi)核符號(hào)到它們的起始地址,在調(diào)試期間可以用它將內(nèi)存地址轉(zhuǎn)換成函數(shù)和變量名。

可能會(huì)遇到的問題

與普通用戶空間的應(yīng)用程序相比,Linux內(nèi)核有多個(gè)特殊的屬性,下面是我認(rèn)為最重要的一些不同:

◆內(nèi)核既不訪問C庫也不訪問標(biāo)準(zhǔn)C頭;

◆內(nèi)核是用GNU C編碼的;

◆內(nèi)核缺少用戶空間提供的內(nèi)存保護(hù);

◆內(nèi)核不能容易地執(zhí)行浮點(diǎn)運(yùn)算;

◆內(nèi)核有一個(gè)小型的固定大小的進(jìn)程堆棧;

◆由于內(nèi)核支持異步中斷和SMP,因此同步和并發(fā)是內(nèi)核主要擔(dān)心的問題;

◆可移植性也很重要。

下面我們就逐個(gè)來了解一下這些問題,所有內(nèi)核開發(fā)人員都必須記住它們。

#p#

無libc或標(biāo)準(zhǔn)頭

和用戶空間應(yīng)用程序不一樣,內(nèi)核并沒有鏈接到標(biāo)準(zhǔn)的C庫,也沒有鏈接到任何其它的庫,這樣設(shè)計(jì)的原因有很多,包括如先有雞還是先有蛋的問題,但主要原因還是速度和內(nèi)核大小,不要說完整的C庫,就是它的一個(gè)子集也夠大,內(nèi)核太大只會(huì)導(dǎo)致效率低下。

不要擔(dān)心,許多常用的libc函數(shù)都在內(nèi)核中實(shí)現(xiàn)了,例如,常見的字符串操作函數(shù)就位于lib/string.c中,只需要包括它的頭文件<linux/string.h >就可以了。

這里的頭文件指的是內(nèi)核源代碼樹中的頭文件,內(nèi)核也只能使用樹內(nèi)的頭文件,基礎(chǔ)文件位于源代碼根目錄的include/目錄下,例如,<linux/inotify.h>頭文件就位于include/linux/inotify.h。

與架構(gòu)相關(guān)的頭文件則位于arch/<architecture>/include/asm,例如,如果在x86架構(gòu)下編譯,與你架構(gòu)相關(guān)的文件就是arch/x86/include/asm,只需要在引用這些頭的地方加上asm/前綴即可,如<asm/ioctl.h>。

漏掉的大部分都是類似printf()這樣的函數(shù),內(nèi)核不會(huì)使用printf(),但它提供了printk()函數(shù),其表現(xiàn)絕不比printf()差,printk()會(huì)拷貝格式化的字符串到內(nèi)核日志緩沖區(qū),syslog程序就是從這里讀取信息的,其用法也和printf()類似:

printk("Hello world! A string '%s' and an integer '%d'\n", str, i);

printf()和printk()之間最大的不同是,printk()允許你指定一個(gè)優(yōu)先級(jí)標(biāo)記,syslogd使用這個(gè)標(biāo)記確定在哪里顯示內(nèi)核消息,下面是一個(gè)使用優(yōu)先級(jí)標(biāo)記的示例:

printk(KERN_ERR "this is an error!\n");

注意在KERN_ERR和打印的消息之間沒有逗號(hào),這是故意這么設(shè)計(jì)的,優(yōu)先級(jí)使用一個(gè)預(yù)定義的字符定義,在編譯期間它與打印的信息是串聯(lián)的。

GNU C

和許多Unix內(nèi)核類似,Linux內(nèi)核也是用C編寫的,但也許會(huì)讓人很意外,內(nèi)核不是用嚴(yán)謹(jǐn)?shù)腁NSI C編寫的,內(nèi)核開發(fā)人員用的卻是gcc(GNU編譯器集,包含了編譯內(nèi)核和Linux C程序的C編譯器)中的各種語言擴(kuò)展。

內(nèi)核開發(fā)人員同時(shí)使用了C語言的ISO C99和GNU C擴(kuò)展,這些變化讓Linux內(nèi)核與gcc結(jié)合得更緊密,但最近又出現(xiàn)了一個(gè)編譯器 – 英特爾的C編譯器 – 也對(duì)gcc的功能支持得相當(dāng)好,因此也可以用它來編譯Linux內(nèi)核。最低支持的gcc版本是3.2,建議采用gcc 4.4或更高的版本編譯。使用ISO C99擴(kuò)展也是可以的,因?yàn)镃99是C語言的官方版本。

內(nèi)聯(lián)函數(shù)

C99和GNU C都支持內(nèi)聯(lián)函數(shù),內(nèi)聯(lián)函數(shù)是直接插入到每個(gè)函數(shù)調(diào)用的位置的,消除了函數(shù)調(diào)用和返回的開銷,允許進(jìn)一步優(yōu)化,因?yàn)榫幾g器可以同時(shí)優(yōu)化調(diào)用者和被調(diào)用函數(shù),但它也有缺點(diǎn),代碼大小會(huì)增加,因?yàn)楹瘮?shù)的內(nèi)容被直接復(fù)制到所調(diào)用者內(nèi)部了,因此也會(huì)增加內(nèi)存消耗和指令緩存空間。內(nèi)核開發(fā)人員一般在小型時(shí)間很關(guān)鍵的函數(shù)中才會(huì)使用內(nèi)聯(lián)函數(shù)。

定義函數(shù)時(shí),使用static和inline關(guān)鍵字聲明內(nèi)聯(lián)函數(shù),例如:

static inline void wolf(unsigned long tail_size)

函數(shù)必須先聲明后使用,否則編譯器就不能使函數(shù)內(nèi)聯(lián),一般做法是將內(nèi)聯(lián)函數(shù)放在頭文件中,因?yàn)樗鼈儽粯?biāo)記為static,不會(huì)創(chuàng)建輸出函數(shù),如果內(nèi)聯(lián)函數(shù)僅在一個(gè)文件中使用,可以放在該文件的頂部。

在內(nèi)核中,與復(fù)雜的宏相比,出于安全和可讀性方面考慮,內(nèi)聯(lián)函數(shù)是首選。

內(nèi)聯(lián)匯編

Gcc C編譯器允許在C函數(shù)中嵌入?yún)R編指令,asm()編譯器指令用于內(nèi)聯(lián)匯編代碼,例如,這個(gè)內(nèi)聯(lián)匯編指令執(zhí)行x86處理器的rdtsc指令,返回時(shí)間戳寄存器(tsc)的值:

unsigned int low, high;
asm volatile("rdtsc" : "=a" (low), "=d" (high));
/* low and high now contain the lower and upper 32-bits of the 64-bit tsc */

Linux內(nèi)核是用C和匯編語言混合編寫的,與底層硬件相關(guān)的代碼很多都是用匯編語言寫的,剩下的大部分內(nèi)核代碼都是直接用C編寫的。

分支注解

Gcc C編譯器內(nèi)置了一個(gè)指令優(yōu)化條件分支,內(nèi)核將這個(gè)打包成易于使用的宏 - likely()和unlikely()。

先看下面這樣的if語句:

if (error) {
        /* ... */
}

將這個(gè)分支標(biāo)記為非常不可能采用

/* we predict 'error' is nearly always zero ... */
if (unlikely(error)) {
        /* ... */
}

相反,將這個(gè)分支標(biāo)記為非??赡懿捎?/p>

/* we predict 'success' is nearly always nonzero ... */
if (likely(success)) {
        /* ... */
}

當(dāng)分支指令已經(jīng)知道一個(gè)優(yōu)先級(jí),或你想在一種情況下優(yōu)化另一種情況時(shí)應(yīng)該使用上述指令,最重要的是,當(dāng)分支正確標(biāo)記時(shí),這些指令會(huì)提升性能,但如果分支標(biāo)記錯(cuò)誤則會(huì)降低性能,在內(nèi)核代碼中,unlikely()要使用得更多,因?yàn)閕f語句傾向于表示一種特殊情況。

無內(nèi)存保護(hù)

當(dāng)用戶空間的應(yīng)用程序嘗試一個(gè)非法的內(nèi)存訪問時(shí),內(nèi)核可以捕捉到錯(cuò)誤,發(fā)送SIGSEGV信號(hào),殺掉進(jìn)程,如果內(nèi)核嘗試一個(gè)非法的內(nèi)存訪問時(shí),結(jié)果就不受控制了,因?yàn)檎l也無法去控制內(nèi)核,這也是內(nèi)核最主要的失誤。

此外,內(nèi)核內(nèi)存也是不可分頁的,因此你消耗的每個(gè)內(nèi)存字節(jié)都比物理內(nèi)存的一個(gè)字節(jié)要少。

不能(容易)使用浮點(diǎn)數(shù)

當(dāng)用戶空間進(jìn)程使用浮點(diǎn)指令時(shí),內(nèi)核要負(fù)責(zé)處理從整型到浮點(diǎn)模式的轉(zhuǎn)換。

與用戶空間不一樣,內(nèi)核不能無縫支持浮點(diǎn)數(shù),因?yàn)樗约翰荒茌p易地捕捉到自己,在內(nèi)核中使用浮點(diǎn)數(shù)需要手動(dòng)保存和恢復(fù)浮點(diǎn)數(shù)寄存器,因此除非卻有必要,否則盡量不要在內(nèi)核中做浮點(diǎn)運(yùn)算。

小型,固定大小的堆棧

用戶空間可以靜態(tài)分配許多不同的堆棧,包括巨型結(jié)構(gòu)和千元數(shù)組,這個(gè)行為是合法的,因?yàn)橛脩艨臻g有很大的堆棧,并可以動(dòng)態(tài)增長。

內(nèi)核堆棧不大也不是動(dòng)態(tài)的,相反,它很小且是固定的,內(nèi)核堆棧的精確大小根據(jù)架構(gòu)有所不同,在x86上,堆棧大小是在編譯時(shí)確定的,一般是4KB或8KB,歷史上,內(nèi)核堆棧有2頁,通常表示它處于32位架構(gòu)上,大小是8KB,如果是16KB就表示是64位架構(gòu),總之大小是固定的,每個(gè)進(jìn)程接收它自己的堆棧。

同步和并發(fā)

內(nèi)核最容易受競爭條件影響,和一個(gè)單線程的用戶空間應(yīng)用程序不一樣,有許多內(nèi)核特性允許同時(shí)訪問共享資源,因此需要同步以防止競爭,特別是:

◆Linux是一種搶占式多任務(wù)操作系統(tǒng),進(jìn)程是由內(nèi)核的進(jìn)程調(diào)度器隨意調(diào)度和再次調(diào)度的,內(nèi)核必須在這些任務(wù)之間同步;

◆Linux支持對(duì)稱多處理(SMP),因此,如果沒有適當(dāng)?shù)谋Wo(hù),在兩個(gè)或多個(gè)處理器上同時(shí)執(zhí)行的內(nèi)核代碼可能會(huì)同時(shí)訪問相同的資源;

◆中斷是異步發(fā)生的,因此,如果沒有適當(dāng)?shù)谋Wo(hù),在訪問資源期間也可能發(fā)生中斷,中斷處理程序可能就會(huì)訪問到相同的資源;

◆Linux是有優(yōu)先權(quán)的,因此,如果沒有適當(dāng)?shù)谋Wo(hù),內(nèi)核代碼可能會(huì)優(yōu)先執(zhí)行,訪問其它代碼正在使用的資源。

解決這些問題的一般方法是自旋鎖和信號(hào)量。

可移植性的重要性

雖然用戶空間應(yīng)用程序一般不會(huì)太重視可移植性,但Linux的確是一個(gè)可移植性操作系統(tǒng),應(yīng)該保持一致,這意味著與架構(gòu)無關(guān)的C代碼必須在大量的系統(tǒng)上正確地編譯和運(yùn)行,與架構(gòu)相關(guān)的代碼必須在內(nèi)核源代碼樹中使用特定的目錄分隔開。

總結(jié)

可以肯定,內(nèi)核有它獨(dú)特的性質(zhì),它有它自己的一些原則,不過,內(nèi)核的復(fù)雜性和障礙與其它大型軟件項(xiàng)目相比,并沒有什么大的不同,Linux開發(fā)道路上最重要的一步是認(rèn)識(shí)到內(nèi)核并不可怕,不熟悉?當(dāng)然!不可逾越?當(dāng)然不是!

原文地址:http://www.informit.com/articles/article.aspx?p=1610334

【編輯推薦】

  1. 7月第2周系統(tǒng)升級(jí)錄:有關(guān)Linux內(nèi)核集體升遷的那些事兒
  2. Linux內(nèi)核修煉之道
  3. Linux管理員們,該刷新內(nèi)核了

 

責(zé)任編輯:yangsai 來源: 51CTO.com
相關(guān)推薦

2021-09-28 07:12:09

Linux內(nèi)核入口

2010-08-28 15:38:11

2010-01-07 13:44:54

Linux內(nèi)核代碼

2012-02-19 15:53:02

筆記本評(píng)測

2022-03-03 18:18:53

BPF解釋器系統(tǒng)

2009-12-15 17:10:39

優(yōu)化Linux

2009-12-17 13:40:42

Linux網(wǎng)卡安裝

2009-12-10 10:40:21

Linux ldd

2009-12-15 14:29:04

2010-01-07 15:00:39

Redhat Ente

2009-12-14 17:13:04

Linux系統(tǒng)修改共享

2009-12-14 16:31:00

Linux安裝支付寶

2009-12-11 10:55:16

Linux啟動(dòng)腳本

2009-12-25 17:35:39

Linux安裝real

2021-02-20 06:08:07

LinuxWindows內(nèi)核

2009-12-09 14:56:54

Linux查看目錄文件

2009-12-10 10:18:44

Apache安裝

2009-12-03 17:50:04

Linux Samba

2009-12-14 18:04:38

Linux命令創(chuàng)建快照

2009-12-16 11:11:10

硬盤讀寫速度
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)