我正在向linux Kernel 3.19添加系统调用。尝试在Ubuntu 14.04 LTS中为x86 arch添加系统调用'add'。 src = 3.19 source
在src / arch / x86 / syscalls / syscall_64.tbl中添加了条目。
323 common add sys_add
将系统调用原型添加到src / include / syscalls.h。
asmlinakge sys_add(int i,int j);
在 fs 目录中输入 add.c ,在 fs / Makefile 中添加 add.o
在档案 src / include / uapi / asm-generic / 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
我错过了什么?
答案 0 :(得分:1)
您缺少一小段汇编代码,汇编后会显示为C-linkable符号。
如果你这样做:
ar t /usr/lib/libc.a | grep write.o
你会看到(可静态链接的)C库有一个名为“write.o”的小文件。这包含一小段汇编代码,用于定义在__libc_write
之外可见的符号write.o
。那个小块的汇编代码将值1放在一个特定的寄存器中,这是Linux和Unix内核所知的“写”系统调用,非常小心地设置其他寄存器,然后执行syscall
指令(在我的x86_64机器上。)
您必须为“添加”系统调用创建这样的汇编代码。或者,就像你一直在做的那样,你可以进行syscall
系统调用,编写一个普通的C函数来使它看起来你已经有add()
系统调用。
您没有说明您正在使用的架构(x86或x86_64),但这里是write(2)
的x86_64实现。它确实正确设置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;
}