linux添加一個系統調用(syscall)

添加系統調用函數頭文件

在include/linux/syscalls.h文件中的#endif前添加自己的系統調用函數聲明,內容如下:

asmlinkage long sys_test(void);

添加系統調用實現源碼

隨便找一個文件,我們在這個文件中添加系統調用的源碼SYSCALL_DEFINE0(test) ,內容如下:

SYSCALL_DEFINE0(test)
{
        printk("Hello world!\n");
        return 0;
}

這裏的 SYSCALL_DEFINE0宏表示我們的系統調用是無參的,該宏在上面syscalls.h頭文件中定義。 SYSCALL_DEFINE0的參數個數爲一個,SYSCALL_DEFINEn的函數個數是n個

在系統調用表中添加相應的表項

添加系統調用向量,在arch/x86/syscalls/syscall_64.tbl文件中添加系統調用號和系統調用服務程序入口(如果是32位系統,則修改syscall_32.tbl文件),在313號系統調用後面添加如下內容:

314 common test sys_test

系統調用會去查找sys_call_table這個數組並找到對應的系統調用函數去執行,注意其中有一個關鍵函數do_ni_syscall,(no implement syscall),當系統調用遇到一些限制或者問題時會跳轉到該函數去執行。

arch/arm64/kernel/sys.c:
/*
 * The sys_call_table array must be 4K aligned to be accessible from
 * kernel/entry.S.
 */
void * const sys_call_table[__NR_syscalls] __aligned(4096) = {
    [0 ... __NR_syscalls - 1] = sys_ni_syscall,
#include <asm/unistd.h>
};

這個數組在創建時首先會把所有的數組成員設置爲sys_ni_syscall,而後根據asm/unistd.h中的內容做進一步初始化。其實最終該頭文件會把include/uapi/asm-generic//unistd.h包含進來,也就是這個頭文件會是最終定義數組的地方。如下所示:

__SYSCALL(__NR_bpf, sys_bpf)
#define __NR_execveat 387
__SYSCALL(__NR_execveat, compat_sys_execveat)
#define __NR_userfaultfd 388
__SYSCALL(__NR_userfaultfd, sys_userfaultfd)
#define __NR_membarrier 389
__SYSCALL(__NR_membarrier, sys_membarrier)
#define __NR_mlock2 390
__SYSCALL(__NR_mlock2, sys_mlock2)
#define __NR_copy_file_range 391
__SYSCALL(__NR_copy_file_range, sys_copy_file_range)
#define __NR_preadv2 392
__SYSCALL(__NR_preadv2, compat_sys_preadv2)
#define __NR_pwritev2 393
__SYSCALL(__NR_pwritev2, compat_sys_pwritev2)

我們添加系統調用之後也需要在此數組中添加一個元素,例:

#define __NR_test 394
__SYSCALL(__NR_test, sys_test)

在數組中添加元素之後,還需要更新這個數組元素的個數,例:

arch/arm64/include/sam/unistd.h
#define __NR_compat_syscalls 395//394+1

添加系統調用號

他在unistd.h的文件中,每個系統調用號都已_NR_開頭,我們添加系統調用號如下所示:

#define __NR_test 290
__SYSCALL(__NR_test,     sys_test)

#undef __NR_syscalls
#define __NR_syscalls 292//291+1

應用測試程序

我們創建一個應用測試程序,源碼如下所示:

#include <linux/unistd.h>
#include <sys/syscall.h>
#include <stdio.h>

int main(void)
{
        long ret= syscall(290);
        printf("%s %d ret = %d\n", __func__,__LINE__,ret);

        return 0;
}

 

發佈了106 篇原創文章 · 獲贊 9 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章