????????想要做一次編譯linux內(nèi)核并添加系統(tǒng)調(diào)用的實驗稽物,于是在網(wǎng)上找了許多教程,沒有找到特別合適的折欠,許多命令在作者這里并不適用贝或,現(xiàn)在經(jīng)過查閱了許多資料終于實驗結(jié)束吼过,把整個實驗的詳細過程分享在這里供大家參考。本文中對一些原理性的知識并沒有過多的解釋咪奖,只是無腦的進行下一步吧盗忱,如有問題可以一起討論,謝謝羊赵。
本文作者使用的系統(tǒng)是ubuntu16.04趟佃,內(nèi)核版本4.10
將要編譯的內(nèi)核版本是4.4.77,linux內(nèi)核建議在官方網(wǎng)站進行下載昧捷,附上鏈接Index of /pub/linux/kernel/
下面正式開始編譯linux闲昭,將想要編譯的linux內(nèi)核下載到本地,將下載的壓縮包復(fù)制到/usr/src/目錄下靡挥,之后進行解壓
cp linux-4.4.77.tar.gz /usr/src/
tar -xzvf?linux-4.4.77.tar.gz
進入文件夾中序矩,進行第一步,添加系統(tǒng)調(diào)用跋破。
1.添加系統(tǒng)調(diào)用號
vim ./arch/x86/entry/syscalls/syscall_64.tbl?
2. 為頭文件添加系統(tǒng)調(diào)用函數(shù)的聲明
此處可以看做是c語言編程時要在頭文件聲明函數(shù)毒返,只是此時是在不同文件夾下進行操作
vim ./include/linux/syscalls.h
將下面兩行代碼添加到文件末尾處
asmlinkage long sys_hello(void);
asmlinkage long sys_mycopy(const char *src_file, const char *copy_file);
到這里頭文件已經(jīng)聲明了函數(shù)租幕,接下來要在源文件中實現(xiàn)函數(shù)的功能
3. 編寫函數(shù)的功能
asmlinkage long sys_hello(void)
{
printk("hello, world!");
return 1;
}
asmlinkage long sys_mycopy(const char *src_file, const char *copy_file)
{
int infd, outfd, count;
char buf[256];
mm_segment_t fs;
fs=get_fs();
set_fs(get_ds());
if((infd=sys_open(src_file, O_RDONLY, 0)) == -1)
{
return 1;
}
if((outfd=sys_open(copy_file, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) == -1)
{
return 2;
}
while((count = sys_read(infd, buf, 256)) > 0)
{
if(sys_write(outfd, buf, count) != count)
return 3;
}
if(count == -1)
return 4;
sys_close(infd);
sys_close(outfd);
set_fs(fs);
return 0;
}
4. 編譯linux內(nèi)核與安裝
到這里就可以運行?make menuconfig?命令了,但是值得一提的是拧簸,此處遇到了報錯令蛉,是由于相關(guān)的庫沒有安裝,報錯中會提示需要安裝哪個庫狡恬,經(jīng)過總結(jié)大概可以直接運行下列命令進行安裝珠叔,基本可以解決
sudo apt-get install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc
此時再運行make menuconfig命令,就會有一個圖形界面顯示
選擇save后弟劲,exit即可祷安,不需進行其他操作。
之后點擊輸入make兔乞,即可開始編譯汇鞭。此處第一次進行編譯時,報錯提示空間不足庸追,注意:第一次時分配20G磁盤空間不足霍骄,第二次便分配了30G磁盤空間,沒有報錯淡溯,成功運行读整。此處等待時間較長,和個人電腦配置有關(guān)咱娶。
下面繼續(xù)進行兩項操作米间,此處并沒有遇到問題强品,作者直接把命令放在下面(都要使用管理員權(quán)限才可以運行)
sudo make modules_install
sudo make install
到這里linux內(nèi)核編譯就已經(jīng)全部結(jié)束了,之后我們要確定引導(dǎo)程序的啟動順序屈糊。
5. 修改開機啟動引導(dǎo)
這里我們依然需要執(zhí)行兩行命令
update-initramfs -c -k 4.4.77 //這里填寫自己剛剛編譯過的linux內(nèi)核的版本
update-grub //這行命令自動尋找/boot/文件夾下的內(nèi)核版本的榛,并自動添加到grub的配置文件
此時我們進入到/boot/grub/目錄下查看grub.cgf,可以看到我們要編譯的內(nèi)核版本已經(jīng)顯示在文件中逻锐。
cat /boot/grub/grub.cfg
之后作者reboot啟動夫晌,但是發(fā)現(xiàn)uname -r 后還是linux-4.10 generic,因為開機時沒有選擇要啟動的內(nèi)核版本昧诱,于是繼續(xù)查看剛剛修改過的grub配置文件慷丽,這里作者注意到此文件的上方提示不能修改此文件,它是由grub-mkconfig自動生成的鳄哭,
作者按照提示找到/etc/default/grub文件,看到對GRUB_DEFAULT的設(shè)置以及是否隱藏選擇引導(dǎo)啟動菜單纲熏。因此使用#注釋掉兩行妆丘,之后要使用下面的命令更新,即更新/boot/grub/grub.cfg文件
sudo update-grub
之后再次reboot局劲,進入到grub啟動選擇界面勺拣,選擇linux 4.4.77
進入到系統(tǒng)后,再次使用uname -r命令查看鱼填,
這里可以看到linux內(nèi)核版本變?yōu)?.4.77药有,說明已經(jīng)成功。
6. 檢驗添加系統(tǒng)調(diào)用函數(shù)是否成功
#include#include#include#includeint main()
{
? ? ? ? long int tmp = syscall(546);
? ? ? ? printf("system call sys_hello return %ld\n", tmp);
????????//此條命令用來執(zhí)行復(fù)制操作苹丸,參數(shù)1為系統(tǒng)調(diào)用函數(shù)號愤惰,參數(shù)2為原文件,參數(shù)3為輸出文件
????????//syscall(547,"test.html","resule.html");
? ? ? ? return 0;
}
gcc命令進行編譯赘理,之后執(zhí)行
gcc test.c -o test?
./test
dmesg //這里需要使用dmesg命令查看printk輸出到信息
到這里就全部結(jié)束了宦言,本文借鑒了不少大佬的經(jīng)驗,還有許多個人博客的經(jīng)驗商模,如有侵權(quán)奠旺,可聯(lián)系刪帖。