メインコンテンツまでスキップ

システムコールの追加

システムコールを追加するためのチュートリアルです.

環境

  • Linux kernel 5.8.13
  • CPU: x86_64

チュートリアル

システムコールの登録

arch/x86/entry/syscalls/syscall_64.tbl に新しいシステムコールのエントリを追加します.使われていないシステムコール番号を使って次のように hello_syscall を追加します.

 437	common	openat2			sys_openat2
438 common pidfd_getfd sys_pidfd_getfd
439 common faccessat2 sys_faccessat2
+440 common hello_syscall sys_hello_syscall

#
# x32-specific system call numbers start at 512 to avoid cache impact

新しいシステムコールの本体の追加

ここでは新たなシステムコールを my_syscall/ ディレクトリに追加する前提で話を進めます.システムコールの本体の処理は my_syscalls/my_syscalls.cSYSCALL_DEFINEk マクロを使用して次のように記述します.

#include <linux/kernel.h>
#include <linux/syscalls.h>
#include "my_syscall.h"

SYSCALL_DEFINE0(hello_syscall)
{
printk(KERN_INFO "hello_syscall: Hello world!\n");
return 0;
}

k はシステムコールの引数の数に関係します.例えば引数が1つの場合は次のように記述します.

SYSCALL_DEFINE1(hello_syscall, int, arg)
{
printk(KERN_INFO "hello_syscall: arg = %d\n", arg);
return 0;
}

次に my_syscalls/my_syscalls.h にヘッダファイルを追加します.

asmlinkage long sys_hello_syscall(void);

include/linux/syscalls.h にも同様にプロトタイプ宣言を追加します.

 asmlinkage long sys_pidfd_send_signal(int pidfd, int sig,
unsigned int flags);
asmlinkage long sys_pidfd_getfd(int pidfd, int fd, unsigned int flags);

+/* my_syscalls/my_syscalls.c */
+asmlinkage long sys_hello_syscall(void);
+
/*
* Architecture-specific system calls
*/

Makefile の修正

最初に次の内容の my_syscalls/Makefile を追加します.

obj-y:=my_syscalls.o

次に Makefile を修正し, my_syscalls/ をカーネルに加えるように設定します.

core-y		+= kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ my_syscalls/

コンパイルとインストール

Install new kernel.

make -j8 && make modules_install && make install
grub-mkconfig -o /boot/grub/grub.cfg
reboot

テスト

確認用のプログラム:

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

#define HELLO_SYSCALL 440

int main(int argc, char **argv)
{
syscall(HELLO_SYSCALL);
return 0;
}

ログの確認:

user@host ~ $ dmesg -w
...
[ 169.128284] hello_syscall: Hello world!