乾貨 | Linux內核編譯與系統調用教程(基於Ubuntu 18.04,究極無敵簡單)
Linux內核編譯與系統調用教程(基於Ubuntu 18.04,究極無敵簡單)
一、內核與系統調用
1.1 內核(Kernel)簡介
- 內核(Kernel),是一個操作系統的核心。它負責管理系統的進程、內存、設備驅動程序、文件和網絡系統,決定着系統的性能和穩定性。
衆所周知,Linux的一個重要的特點就是開源,所有的內核源程序都可以在路徑/usr/src/linux
下找到,大部分應用軟件也都是遵循GPL而設計的,你都可以獲取相應的源程序代碼。全世界任何一個軟件工程師都可以將自己認爲優秀的代碼加入到其中,由此引發的一個明顯的好處就是Linux修補漏洞的快速以及對最新軟件技術的利用。而Linux的內核則是這些特點的最直接的代表。
由於Linux的源程序是完全公開的,任何人只要遵循GPL,就可以對內核加以修改併發布給他人使用。Linux的開發採用的是集市模型(bazaar,與cathedral–教堂模型–對應),爲了確保這些無序的開發過程能夠有序地進行,Linux採用了雙樹系統。一個樹是穩定樹(stable tree),另一個樹是非穩定樹(unstable tree)或者開發樹(development tree)。一些新特性、實驗性改進等都將首先在開發樹中進行。
如果在開發樹中所做的改進也可以應用於穩定樹,那麼在開發樹中經過測試以後,在穩定樹中將進行相同的改進。一旦開發樹經過了足夠的發展,開發樹就會成爲新的穩定樹。開發數就體現在源程序的版本號中;源程序版本號的形式爲x.y.z:對於穩定樹來說,y是偶數;對於開發樹來說,y比相應的穩定樹大一(因此,是奇數)。
1.2 系統調用簡介
計算機系統的各種硬件資源是有限 的,在現代多任務操作系統上同時運行的多個進程都需要訪問這些資源,爲了更好的管理這些資源進程是不允許直接操作的,所有對這些資源的訪問都必須有操作系統控制。也就是說操作系統是使用這些資源的唯一入口,而這個入口就是操作系統提供的系統調用(System Call)。在linux中系統調用是用戶空間訪問內核的唯一手段,除異常和陷入外,他們是內核唯一的合法入口。
PS: 這裏還涉及到了核態與目態的一些知識,大家可以去操作系統原理中找找看,這裏就不過多贅述了 :)
二、內核編譯目的
Linux作爲一個自由軟件,在廣大愛好者的支持下,內核版本不斷更新。新的內核修訂了舊內核的bug,並增加了許多新的特性。如果用戶想要使用這些新特性,或想根據自己的系統度身定製一個更高效,更穩定的內核,就需要重新編譯內核。
通常,更新的內核會支持更多的硬件,具備更好的進程管理能力,運行速度更快、 更穩定,並且一般會修復老版本中發現的許多漏洞等,經常性地選擇升級更新的系統內核是Linux使用者的必要操作內容。
爲了正確的合理地設置內核編譯配置選項,從而只編譯系統需要的功能的代碼,一般主要有下面四個考慮:
- 自己定製編譯的內核運行更快(具有更少的代碼)
- 系統將擁有更多的內存(內核部分將不會被交換到虛擬內存中)
- 不需要的功能編譯進入內核可能會增加被系統攻擊者利用的漏洞
- 將某種功能編譯爲模塊方式會比編譯到內核內的方式速度要慢一些
三、系統調用與內核編譯教程(一看就會)
預先說明,我本人使用的18.04 LTS的kernel版本爲:5.3.0-51-generic
,重新編譯的kernel選擇了最新的穩定版5.6.15
。
3.1 下載內核源代碼
進入官網下載所需的內核源碼,如圖(我選擇的是stable 5.6.15
)。
簡要說明一下各個版本:
- mainline:由Linux內核的最早作者Linus Torvalds製作,大概每十週發佈一次,是對重大變化的整合以及bug的維護。
- longterm:長期維護版本。
- stable:穩定版。
源碼下載完成後,解壓並拷貝至/usr/src/
路徑下。
3.2 設置系統調用
首先執行cd /usr/src/你自己解壓的源碼文件夾
切換路徑
- 在系統調用表中添加自定義的系統調用表項目,執行以下指令:
sudo gedit arch/x86/entry/syscalls/syscall_64.tbl
在不覆蓋原有系統調用的前提下(具體可以閱讀內部註釋),添加自己的系統調用,官方建議以sys_
爲函數名的首部,如下圖所示:
- 將系統調用號定義到相應頭文件,執行以下代碼:
sudo gedit include/linux/syscalls.h
進行相關定義,如圖所示:
- 增加系統調用具體功能,首先執行以下代碼:
sudo gedit kernel/sys.c
在末尾實現自定義系統調用的具體功能:
系統調用部分到這裏就結束了。
3.3 重新編譯內核
- 執行如下命令:
sudo make menuconfig
根據提示信息進行相關的依賴安裝,然後繼續執行知道內核配置的圖形化界面出現,這裏提供我在這一過程中用到的一些命令:
sudo make menuconfig
sudo apt install libncurses-dev
sudo apt install flex
sudo apt install bison build-essential
build-essential裏面包含了很多開發必要的軟件包,很全,很方便。如g++和其相關依賴庫。
- 內核配置圖形化界面
如圖,若沒有特殊需求可以直接exit-->save
,當前內核的配置會保存在當前目錄下的.config文件當中,然後進行下一步操作。
注:
*
代表編譯到內核當中,M
表示作爲內核的模塊。可使用shift+?
查看幫助。
選擇什麼根據目標系統的特性決定,一般來說,嵌入式系統一般會使內核越小越好,因爲資源本身就有限,內核小會相對穩定,啓動速度也會相對快一些。
- 執行指令
make
,若提示缺少依賴,執行如下命令:
sudo apt install libssl-dev
- 執行如下命令:
sudo make -j4
此處使用sudo
是爲了防止編譯時權限不足,而參數-j4
則表示在多核cpu上並行多線程處理,適當使用可以有效提升編譯速度!我周邊大部分人在這一階段用時三小時左右,加上-j4
這一參數後編譯內核耗時一個半小時。
- 編譯完成後,執行如下命令:
sudo make modules_install
sudo make install
可以看到,grub引導也自動更新了,真的很方便很簡單!
如果遇到如下提示:
I: The initramfs will attempt to resume from /dev/sda5
I: (UUID=423e90ce-b29e-4edd-be81-d5273deb4ed6)
I: Set the RESUME variable to override this.
解決方案如下:
執行命令:
sudo gedit /etc/initramfs-tools/conf.d/resume
然後添加如下內容:
RESUME=UUID=提示的UUID
執行下述命令後即可解決。
sudo update-initramfs -u -k all
內核編譯部分到這裏就結束了,驗證一下是否成功:
3.4 測試驗證
可以看到,無論哪種方式下查看內核版本,都是重新編譯後的新版本kernel了!
再看看自定義系統調用是否成功:
OK,自定義系統調用也成功執行!完美!
至此,大功告成!希望能給大家提供到一定幫助~