為Linux-3.10.1核心新增系統呼叫

始祖魚發表於2018-02-07

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

        測試結果如下圖所示:


        如果能夠看到上述結果,表示你的第一個自定義系統呼叫已經新增成功。

本文轉載於 靈躍雲:原文連結



相關文章