在Linux內核中添加系統調用,並編譯內核

1 環境準備

    運行系統:vmware下安裝的ubuntu10.10 32bit桌面版。linux

    編譯內核版本: linux-2.6.32.63ubuntu

    內核目錄: /home/wanchouchou/linuxKernel/linux-2.6.32.63vim

    爲了方便,使用chmod 777 -R linux-2.6.32.63/ 將全部的內核文件都改成全權限,這樣就能夠在非root狀態修改文件進行編譯了。函數

2 添加系統調用

     首先進入linux-2.6.32.63目錄下。之後的文件路徑都是以此目錄爲「根目錄」的。es5

2.1 在系統函數表中添加表項

     進入arch/x86/kernel目錄下,而後vim syscall_table_32.S,在此文件的最後一行添加本身的系統調用表項:spa

1 .long sys_rt_tgsigqueueinfo    /* 335 */
2 .long sys_perf_event_open
3 .long sys_mycall      //這是咱們本身添加的表項

     好了,下面開始添加系統調用號。code

2.2 添加本身的系統調用號

    如今進入目錄 arch/x86/include/asm,該目錄下有三個文件unistd_32.h, unistd_64.h, unistd.h。因爲咱們編譯的是32位內核,因此須要在unistd_32.h中添加系統調用號。blog

vim unistd_32.h,在最後添加代碼:get

1 #define __NR_perf_event_open    336
2 #define __NR_mycall       337 //添加的
3 #ifdef __KERNEL__
4 
5 /* 本來爲337,可是因爲咱們添加了一行,因此改338*/
6 #define NR_syscalls             338  

2.3 編寫本身系統調用的實現函數

   因爲系統調用必須編譯到核心的內核鏡像中去。因此咱們將此函數的實現寫到kernel/sys_i386_32.c中:it

1 //引入頭文件
2 #include <asm/page.h>
3 ........
4 //添加函數代碼
5 asmlinkage  long sys_mycall(void){
6     return THREAD_SIZE;
7 }

 

3 編譯內核    

      如今就能夠回到linux-2.6.32.63目錄進行編譯了。若是之前編譯過內核,最好使用make mrproper和make clean命令來清除以前的編譯殘留文件。若是是第一次編譯內核,那麼就須要對內核的編譯選項進行配置,這裏推薦使用make menuconfig。若是鍵入該命令後提示缺乏ncurses庫文件的話,就使用sudo apt-get install libncurses5-dev命令安裝該庫。以後就能夠進行menuconfig配置了,建議保持默認值便可。

      一切準備就緒,鍵入make命令開始編譯內核!如今能夠泡一桶coffee來慢慢喝了,爲何是一桶?由於時間真的很長~~~

4 編譯並安裝內核模塊

    make modules ,這個相對來講要快一點。10分鐘左右。而後安裝內核模塊: make modules_install 以及安裝內核: make install

5 讓新舊內核都可以加載

   sudo mkinitramfs -o /book/initrd.img-2.6.32.63  //此命令會在/boot目錄下生成initrd.img-2.6.32.63等文件

   sudo update-initramfs -c -k 2.6.32.63              //根據/lib/modules/2.6.32.63文件進行更新。若是此命令出現FATAL: could not load /lib/modules/2.6.32.63的話,就將命令後面的2.6.32.63改成此目錄下的新內核文件名便可(注意:舊內核文件名爲2.6.35-22-generic)。

   sudo update-grub2                                         //自動修改系統的引導配置文件,主要是更新/book/grup/grup.cfg啓動文件。此命令執行完後會在grup.cfg中添加新內核的啓動項

6 進入grup選擇須要啓動的內核

   在ubuntu10.10默認grup菜單是不會顯示的,也就是說沒法選擇啓動的內核。要想顯示的話,須要按照以下步驟進行操做:

一、把/etc/default/grub文件中的GRUB_HIDDEN_TIMEOUT=0改成大於0的數字,好比4;

二、把/etc/grub.d/30_os-prober文件中全部的set timeout=0中的0改成10.仔細找,不要漏過了;

三、上述修改完成後,執行命令更新grup2: sudo update-grub  //更新/boot/grub/grub.cfg文件

7 重啓

   reboot。這時候在啓動的時候就會停留在grup界面了,裏面有4個選項,每一個內核對應2個,選擇進入2.6.32.63內核。啓動完成後在終端輸入: uname -a 顯示的就是新內核版本了。

8 驗證自定義的系統調用

   如今咱們能夠編寫代碼來驗證自定義的系統調用是否被加入到了內核中:

 

 1 #include<sdtio.h>
 2 #include<unistd.h>
 3 #include<sys/syscall.h>
 4 
 5 #define SYS_mycall   337  //同咱們前面定義的系統調用號相同
 6 
 7 int main(){
 8     long ret = 0;
 9     ret = syscall(SYS_mycall);  //根據系統調用號調用對應的系統調用
10     printf("ThreadSize is: %ld\n", ret);
11     return 0;
12 } 

    須要說明的是,在2.6.20之後的版本是沒有之前的那些系統調用宏定義的(如_syscall0, _syscall1等),必須使用syscall來進行系統調用(能夠經過man syscall獲取參考信息)。同時因爲是系統調用,因此須要root模式下編譯、運行程序。程序運行結果: 8192。

   注意,按理來講,咱們是不須要本身定義SYS_mycall = 337的,可是,若是不這樣的話編譯的時候會提示找不到SYS_mycall,也就是說,它並無被顯示地加入到syscall.h文件中~解決辦法以下:

一、修改/usr/include/asm/unistd_32.h文件,將最後的#define __NR_recvmmsg  337 改成 #define __NR_mycall   337  //貌似系統中根本就沒有recvmmsg只有recvmsg~

二、修改/usr/include/bits/syscall.h文件,在文件開頭位置加入代碼: #define SYS_mycall   __NR_mycall   ;

這樣,咱們就能夠直接在程序中使用SYS_mycall了。

相關文章
相關標籤/搜索