添加系統調用函數頭文件
在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;
}