Ubuntu 18.04環境下編譯Linux內核以及添加系統調用


有個操作系統實驗,然後呢,最開始的實驗內容就是編譯Linux內核,這個東西有些噁心,錯一個結果就錯,而且你還不知道哪裏錯了,好久沒寫文章了,這次就把這個記錄一下吧,順便後排感謝某大佬援助(雖然看不見,手動滑稽)。
關於添加系統調用,雖然有文檔而且步驟詳細,但是我不知道爲什麼就是弄不成功,然後呢我放棄文檔另尋出路,經過百度,我找到了解決方法,詳細看文章吧。

使用工具及環境

版本隨意,我用的是目前的最新版

編譯

先將下載的內核壓縮文件複製到Ubuntu的桌面,方便操作。

sudo tar -xavf linux-4.18.14.tar.xz

解壓壓縮文件到桌面

安裝依賴

就是編譯環境所需要的各種資源,直接安裝就好了。

sudo apt-get install gcc make libncurses5-dev openssl libssl-dev 
sudo apt-get install build-essential 
sudo apt-get install pkg-config
sudo apt-get install libc6-dev
sudo apt-get install bison
sudo apt-get install flex
sudo apt-get install libelf-dev

編譯前的配置

在這一步會打開Kernel的配置程序,可以進行相關的配置,在此不需要進行任何修改,直接Exit即可。

cd ~/Desktop/linux-4.18.14/
sudo cp /boot/config-4.15.0-20-generic .config
sudo make menuconfig

image
image

開始編譯

所謂的編程五分鐘編譯兩小時,就是說的現在,我給的配置,編譯用時2小時20分鐘,我可是有很認真的計時。

sudo make
sudo make modules_install

image

安裝內核

這一步將我們編譯好的內核安裝到我們的Ubuntu系統內部,相關指令如下,安裝完之後記得使用更新操作。

sudo mv  ~/Desktop/linux-4.18.14  /usr/src/
cd /usr/src/linux-4.18.14/
sudo make install
sudo mkinitramfs -o /boot/initrd.img-4.18.14 
sudo update-initramfs -c -k 4.18.14
sudo update-grub2

驗收成果

此時的系統內核其實仍處於原先的版本,使用指令uname -a可以看到當前系統內核信息(Ubuntu 18.04應該是4.15.x的內核)你也可以記住這個信息,方便和之後進行對比。
重啓Ubuntu,重啓之後輸入指令uname -a,可以看到當前的內核信息,已經是4.18.x了。
如下面兩圖
image
image

結果

至此編譯內核的任務就完成了。

系統調用

什麼是系統調用呢?我也不會解釋,點擊此處查看詳細說明

準備階段

其實系統調用就是相當於編寫一個函數插入到系統函數中去,可以方便調用,我覺得,嗯。那麼既然是一個函數,他的寫法其實和正常的函數是一樣的,在頭文件中聲明函數,在源文件中定義函數主體,同時還多了一個步驟,那就是添加一個系統調用id。這是什麼呢?每一個系統調用具有一個id,有了這個我們在調用的時候直接給定id就可以使用所需的系統調用了,而不需要知道他的名稱等,下面就開始吧。
以下所有命令的執行路徑都是上面得到的linux內核文件夾的路徑,即/usr/src/linux-4.18.14/
下列編寫的命令加上sudo的原因是那些是系統只讀文件,如果不給權限他只讀,但是不加sudo也可以,只不過此時保存時輸入:wq會提示失敗,此時使用:w !sudo tee %即可成功保存,隨後退出即可。

聲明和定義系統調用函數

使用命令sudo vim arch/x86/include/asm/syscalls.h,在其中添加一行函數聲明asmlinkage long sys_helloworld(void);,可以隨意添加註釋(當然也沒人看),如下所示
image
使用命令sudo vim kernel/sys.c編寫函數定義主體,在其中按照正常寫法完成這個函數即可,注意修飾詞格式,可以正常添加參數,我這只是用了無參進行舉例,如下所示
image

添加一個系統調用id

使用命令sudo vim arch/x86/entry/syscalls/syscall_64.tbl打開系統調用列表,這裏用到的文件是64位,雖然VM是32位,但是系統是64位的,所以64位文件能用,在其中添加自己的系統調用號,如下所示,id不要和已存在的系統調用重複,後面如果上面都是__64_xx開頭的,也不要管,就像這樣添加333 64 xxx sys_xxx即可
image

進行編譯

上述操作進行完之後呢,這就需要進行操作,經過我今天多次的嘗試我得出了一個小小的結論,我的電腦配置還算可以,我給他雙核雙線程CPU,編譯時間穩定兩小時二三十分鐘左右,當雙核雙線程CPU進行四線程編譯的時候,我的實體機CPU利用率60%左右波動,編譯時間縮短爲一個小時左右,我又繼續作死嘗試,給了四核雙線程CPU,此時其實VM已經認爲是八核了我讓他八線程編譯(我似乎忘了是4還是8),用時接近五十分鐘,僅有十餘分鐘的提升
使用下列命令進行編譯

sudo make clean
#仍採用原內核配置文件
sudo make oldconfig
sudo make 
sudo make modules_install
sudo make install

如果之前系統調用函數寫的有問題的話,這裏出現錯誤後應該會直接停止的,然後直接顯示Error,報錯應該比較人性化。
此時我們可以去喝一桶咖啡聊會天,爲什麼一桶呢?因爲第一次編譯的時候我就睡着了。。。
編譯完成後直接reboot重啓系統。

運行檢驗

重啓之後,我們需要編寫一個小程序檢驗一下我們的系統調用是否可以正常使用,編寫如下.c代碼並保存

#include <stdio.h>
#include <linux/kernel.h>
#include <sys/syscall.h>
#include <unistd.h>
int main(int argc,char **argv){
	//336就是我們剛纔添加的系統調用的id
	long int a=syscall(336);
	printf("System call sys_helloworld return %ld",a);
	return 0;
}

使用gcc進行編譯運行

gcc -o hello hello.c
./hello

結果如下所示,從輸出內容可以看到該系統調用返回值爲0,正好爲我們所編寫的函數的返回值
image

結束

至此添加系統調用就已經實現了。

參考鏈接

給linux系統增加一個系統調用 King_LJames

OK,THANKS FOR READING.BYE BYE~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章