我正在尝试添加一个新的系统调用到linux内核:
asmlinkage long sys_set_status(int status) {
if ((status != 0) && (status != 1))
return -EINVAL; //-22
current->status = status;
return 0;
}
在syscall_64。TBL声明:
334 common set_status sys_set_status
在syscalls.h中声明:
asmlinkage long sys_set_status(int status);
但是当我测试返回值时:
int set_status(int status) {
long r = syscall(334, status);
return (int)r;
}
int main() {
int res = set_status(-1); //illegal status, should return -EINVAL whish is -22
cout << "return value is: " << res << endl;
return 0;
}
我:
返回值为:-1
long r = syscall(334, status);
From man syscall:
返回值由被调用的系统调用定义。在一般情况下,返回0表示成功。返回值-1表示错误,错误编号保存在errno中。
你是不是直接调用系统调用,你是通过libc
syscall
包装器调用它,它执行大约如下:
int syscall(num, ...)
{
/* architecture-specific code to put system call number and args into
appropriate registers */
/* arch-specific code to execute the system call instruction */
int rc = /* arch-specific code to get the result of the system call */ ;
if (rc < 0) { errno = -rc; return -1; }
return 0;
}
如果您不希望发生这种转换,您将不得不自己执行特定于体系结构的部分(在汇编中),然后您将拥有实际的系统调用返回值。
正如受雇俄语所指出的在libc和errno
中设置系统调用包装函数,将系统调用的负返回值转换为返回值-1。因此,期望返回值-1,并且应该检查errno
的值。
很可能errno
将被设置为ENOSYS
而不是EINVAL
,因为内核系统调用代码是用在大多数64位内核上工作的旧格式编写的。应该更新系统调用的内核代码,以使用SYSCALL_DEFINE1
包装器宏(因为系统调用有一个参数),如下所示:
#include <linux/syscalls.h>
SYSCALL_DEFINE1(set_status, int, status)
{
if ((status != 0) && (status != 1))
return -EINVAL; //-22
current->status = status;
return 0;
}
编辑:实际上,如果这是问题,内核应该无法连接由于未定义的符号。但是无论如何您都应该使用新格式(如果可能的话,并且可能不适合2009年之前发布的内核)。
我不确定这个系统调用的意义是什么。当系统调用退出回userland时,任务状态应该设置回0。