Linux 内核函数 returns 1 而不是 EINVAL
Linux kernel function returns 1 instead of EINVAL
我正在尝试向 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);
但是当我测试 return 值时:
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;
}
我得到:
return value is: -1
long r = syscall(334, status);
来自man syscall:
The return value is defined by the system call being invoked. In
general, a 0 return value indicates success. A -1 return value
indicates an error, and an error number is stored in 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;
}
如果您不希望发生这种翻译,则必须自己执行 architecture-specific 部分(在汇编中),然后您将得到 actual 系统调用 return 值.
正如 Employed Russian 的 中指出的那样,来自系统调用的负 return 值被转换为 return 值-1 由 libc 和 errno
中的系统调用包装函数设置。所以 return 值 -1 是预期的,应该检查 errno
的值。
很可能 errno
将被设置为 ENOSYS
而不是 EINVAL
因为内核系统调用代码是用在大多数 64 位上工作的旧格式编写的内核。系统调用的内核代码应更新为使用 SYSCALL_DEFINE1
包装器宏(因为系统调用有 1 个参数),如下所示:
#include <linux/syscalls.h>
SYSCALL_DEFINE1(set_status, int, status)
{
if ((status != 0) && (status != 1))
return -EINVAL; //-22
current->status = status;
return 0;
}
编辑:实际上,如果这是问题所在,内核应该由于未定义的符号而无法 link。但是无论如何您都应该使用新格式(如果可能的话,对于 2009 年之前发布的内核可能不适用)。
我不确定这个系统调用的意义是什么。当系统调用返回用户空间时,任务状态应该设置回 0。
我正在尝试向 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);
但是当我测试 return 值时:
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;
}
我得到:
return value is: -1
long r = syscall(334, status);
来自man syscall:
The return value is defined by the system call being invoked. In general, a 0 return value indicates success. A -1 return value indicates an error, and an error number is stored in 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;
}
如果您不希望发生这种翻译,则必须自己执行 architecture-specific 部分(在汇编中),然后您将得到 actual 系统调用 return 值.
正如 Employed Russian 的 errno
中的系统调用包装函数设置。所以 return 值 -1 是预期的,应该检查 errno
的值。
很可能 errno
将被设置为 ENOSYS
而不是 EINVAL
因为内核系统调用代码是用在大多数 64 位上工作的旧格式编写的内核。系统调用的内核代码应更新为使用 SYSCALL_DEFINE1
包装器宏(因为系统调用有 1 个参数),如下所示:
#include <linux/syscalls.h>
SYSCALL_DEFINE1(set_status, int, status)
{
if ((status != 0) && (status != 1))
return -EINVAL; //-22
current->status = status;
return 0;
}
编辑:实际上,如果这是问题所在,内核应该由于未定义的符号而无法 link。但是无论如何您都应该使用新格式(如果可能的话,对于 2009 年之前发布的内核可能不适用)。
我不确定这个系统调用的意义是什么。当系统调用返回用户空间时,任务状态应该设置回 0。