為Linux-3.10.1內核添加系統調用


轉載自 靈躍雲 :原文鏈接   

1.    寫在前面

        系統調用是操作系統提供給用戶程序調用的一組“特殊”接口。通過這組“特殊”接口,用戶程序可以獲得操作系統內核提供的服務,如文件系統相關系統調用提供的打開文件、關閉文件或讀寫文件服務,時鍾相關的系統調用提供的獲取系統時間、設置系統時間服務等。

        從邏輯上來說,系統調用可被看成是一個內核與用戶空間程序交互的接口——好比一個中間人,把用戶進程的請求傳達給內核,待內核把請求處理完畢后再將處理結果送回給用戶進程。

        一個系統調用的典型調用過程如下圖所示。

 

        系統調用的作用:

        系統服務之所以需要通過系統調用提供給用戶空間,其根本原因是為了對系統進行“保護”。我們知道操作系統的運行空間分為內核空間與用戶空間,它們各自運行在不同的級別中,邏輯上相互隔離,故用戶進程在通常情況下不允許訪問內核數據、不允許使用內核函數,它們只能在用戶空間操作用戶數據,調用用戶空間的函數。但是很多情況下,用戶進程需要獲得系統服務(調用系統程序),這時就必須利用系統提供給用戶的“特殊”接口——系統調用,其特殊性在於規定了用戶進程進入內核的具體位置,即用戶訪問內核的路徑是事先規定好的,只能從規定位置進入內核,而不准許肆意跳入內核。有了上述陷入內核的統一訪問路徑限制,才能有效保證系統內核的安全。我們可以形象地描述上述機制:作為一個游客,你可以買票要求進入野生動物園,但你必須老老實實的坐在觀光車上,按照規定的路線觀光游覽。當然,不准下車,因為那樣太危險,不是讓你丟掉小命,就是讓你嚇壞了野生動物。

        在前述文章“Linux-3.10.1內核的編譯和安裝”(詳見http://www.lingyuecloud.com/Index/details/id/58.html)中,我們知道利用Linux內核的開源特性,可以對Linux系統進行定制化開發、編譯和安裝。例如,通過修改Linux內核源碼,我們定制化開發了一個新功能,那么如何在應用程序中使用這個新功能呢?為此,我們還需要為“應用程序”與“內核中新增的新功能”建立橋梁——即一個能夠連接兩者的系統調用。

        假設我們已經獲得了Linux-3.10.1的源碼包linux-3.10.1.tar.bz2,解壓該源碼包后得到linux-3.10.1文件夾,並切換到該文件夾下(如何獲取包linux-3.10.1.tar.bz2?如何解壓?請詳見http://www.lingyuecloud.com/Index/details/id/58.html——“Linux-3.10.1內核的編譯和安裝”)。接下來,靈躍桌面雲將以Linux-3.10.1內核為例,詳細描述為內核添加一個新的系統調用的過程,下述所有操作都在linux-3.10.1目錄下進行。

 

2.    環境說明

 

注:在下述描述中,涉及在服務器Ubuntu 12.04操作系統環境上的所有操作,均以root身份登錄並執行。

 

3.    為Linux-3.10.1內核添加一個系統調用

 

3.1  系統調用號

 

        Linux系統調用號的作用是在系統調用過程中,將其數值作為下標的在系統調用表中進行索引,從而得到處理該系統調用的函數的地址。

        每個系統調用都有一個唯一的系統調用號,應用程序可以通過系統調用號調用指定的系統調用。

3.2  系統調用表

 

        與Windows系統中的SSDT(System Services Descriptor Table)的作用一樣,Linux系統調用表保留着處理各個系統調用的函數的入口地址;其實際上是一個二維的指針數組[X][Y],X代表系統調用號,Y代表系統調用函數的入口地址。

3.3  添加系統調用lingyuecloudsyscall

 

        1)        添加自定義的系統調用源代碼

        在“linux-3.10.1/kernel”目錄下的sys.c文件中添加自定義的系統調用lingyuecloudsyscall的實現函數。

        打開sys.c文件,添加以下示例代碼:

        #vim kernel/sys.c

asmlinkage long sys_lingyuecloudsyscall (int number){
printk("hello lingyuecloud!Call number is %d\n",number);
return number;

}

 

        2)        修改系統調用表

        系統調用表文件在“linux-3.10.1/arch/x86/syscalls”目錄下的syscall_64.tbl文件中。

        打開syscall_64.tbl,添加新的系統調用指針,如下所示:

        #vim arch/x86/syscalls/syscall_64.tbl

314   64     lingyuecloudsyscall      sys_ lingyuecloudsyscall;

        如下圖所示:

 

        其中,314為lingyuecloudsyscall的系統調用號,應用程序可通過此調用號調用lingyuecloudsyscall系統調用,也可以使用其它的系統調用號,但注意不能與已有的系統調用號重復。64表示適配於64位系統內核環境,相關描述詳情可查閱https://en.wikipedia.org/wiki/X32_ABI。

        3)        添加系統調用lingyuecloudsyscall的函數聲明

        在“linux-3.10.1/include/linux/”目錄下的syscalls.h文件中添加函數聲明。

        打開syscalls.h,在倒數第二行添加下面內容:

        #vim include/linux/syscalls.h

asmlinkage long sys_lingyuecloudsyscall(int num);

        如下圖所示:

 

        4)        重新編譯

        5)        內核

        編譯過程詳見http://www.lingyuecloud.com/Index/details/id/58.html——“Linux-3.10.1內核的編譯和安裝”。

        6)        測試系統調用

        編寫測試程序lingyuecloud_test.c:

#include<stdio.h>

#include<linux/unistd.h>

#include<sys/syscall.h>

int main()

{

      long a;

      a = syscall(314,100);  //調用第314號系統調用,即sys_lingyuecloudcall();

      printf("The number is%d\n",a);

      return 0;

}

 

        編譯測試程序:

        #gcc -o lingyuecloud lingyuecloud_test.c

        測試結果如下圖所示:

 

        如果能夠看到上述結果,表示你的第一個自定義系統調用已經添加成功。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM