2015-03-02 60 views
3

我正在向linux Kernel 3.19添加系統調用。試着在Ubuntu 14.04 LTS中爲x86 arch添加一個系統調用'add'。 SRC = 3.19源通過名稱調用系統調用的麻煩

  1. 添加的條目爲src /拱/ 86 /系統調用/ syscall_64.tbl。

    323 common add sys_add 
    
  2. 向src/include/syscalls.h添加了系統調用原型。

    asmlinakge sys_add(int i,int j); 
    
  3. add.cFS目錄,在FS /生成文件加入add.o

  4. 在文件的src /包括/ uapi/ASM-通用/ unistd.h中

添加的行

#define __NR_add 323 

    __SYSCALL(__NR_add, sys_add); 
  • 編譯和構建內核。這是成功。輸出uname -r給出3.19。

  • 創建了一個程序來測試新的系統調用。

    6.1使用函數系統調用(323,10,15)。這是成功的價值總和(25)印。

    6.2當試圖通過名字來稱呼的系統調用,它給

    /tmp/ccpxRp8C.o: In function `main': 
        testadd1.c:(.text+0x18): undefined reference to `add' 
        collect2: error: ld returned 1 exit status 
    
  • 我在想什麼?

    回答

    1

    您錯過了一小段彙編代碼,彙編時顯示爲C-linkable符號。

    如果你這樣做:

    ar t /usr/lib/libc.a | grep write.o 
    

    ,你會看到(靜態聯)C庫有一個名爲「write.o」的小文件。這包含一小段彙編代碼,它定義了在write.o之外可見的符號__libc_write。這一小段彙編代碼將值1放入特定寄存器中,這是Linux和Unix內核稱爲「寫入」系統調用的數量,非常仔細地設置了其他寄存器,然後執行指令(在我的x86_64機器上)。

    您將不得不爲您的「添加」系統調用創建這樣一段彙編代碼。或者,您可以像您一直在做的那樣調用syscall系統調用,編寫一個簡單的C函數使其看起來像是您已經獲得了系統調用add()

    你沒有說你正在使用什麼樣的架構(x86或x86_64),但是這裏有一個x86_64實現write(2)。它確實設置了errno,並返回了寫入的字節數,但參數類型不正確。

    int 
    linux_write(int fd, const void *data, unsigned long len) 
    { 
    
        long ret; 
        asm volatile ("syscall" : "=a" (ret) : "a" (__NR_write), 
           "D" (fd), "S" (data), "d" (len) : 
           "cc", "memory", "rcx", 
           "r8", "r9", "r10", "r11"); 
        if (ret < 0) 
        { 
         errno = -ret; 
         ret = -1; 
        } 
        return (int)ret; 
    } 
    
    +0

    嗨,感謝您的回覆。上面的代碼是在內核本身完成的?另外,**步驟4 **的用法是什麼? – 2015-03-03 10:33:53

    +0

    @AsishKSahadevan - 不,它駐留在一個單獨的文件中,並自行編譯。那時你已經有了一個目標文件(.o文件),它可以與缺少符號的C程序相鏈接。目標文件提供了符號和執行'syscall'的代碼,它將程序引入內核。第4步是你可以使用'syscall()'通用系統調用執行函數。如果您正在編寫自己的裝配存根,則不需要執行第4步。 – 2015-03-03 13:46:06