linux 系统调用返回 1,Linux内核系统调用返回-1而不是{-1,-256}

我是一个内核新手,面临着一个奇怪的问题.我编写了一个概念验证计算器系统调用,虽然它适用于大多数计算,但当SUBTRACTION结果介于-1到-256之间时它返回-1.如果有人可以对可能发生的事情有所了解,那就会很感激.下面是系统调用代码.

SYSCALL_DEFINE3(calc, int, a, int, b , char, op) {

int res_int;

switch(op) {

case '+': res_int = a + b;

break;

case '-': res_int = a - b;

break;

case '*': res_int = a * b;

break;

case '/': res_int = (a*1000) / b;

break;

}

printk(KERN_INFO "KERNEL CALC RESULT : %d %c %d = %ld",a, op, b, res_int);

return res_int;

}

编辑:

内核版本:Android Linux Kernel 3.10.xxx.

平台:Nexus7 ARM EABI.

我不明白的是它失败的原因. errno完全没用,因为它将-res_int设置为errno.另外,我不明白为什么只有当res_int为{-1,-256}时才会失败.

a = 1200,b = 1300 op =’ – ‘=> res_int = -100是printk打印-100的示例,但在我的用户空间应用程序中,我收到-1.

看起来当res_int为{-1,-256}时,errno被设置为-res_int.

root@android:/data/local # ./calc

Please enter request in 'num1 oper num2' format:

2.45 - 2.2

returned from syscall with res_int = 250

errno = 22, strerror(errno) = Invalid argument

Calculator result = 0.250000

root@android:/data/local # ./calc

Please enter request in 'num1 oper num2' format:

2.2 - 2.45

returned from syscall with res_int = -1

errno = 250, strerror(errno) = Unknown error 250

Calculator result = -0.001000

root@android:/data/local #

解决方法:

你没有提到你的内核版本和平台但是fwiw,从内核的角度来看,系统调用通常在成功时返回零,在错误时返回负数.通常,这是内核人员和应用程序开发人员之间的ABI约定,因此代码可以相互理解.

但是用户程序总是使用C库作为包装来进行系统调用,而C API应该符合API标准.也就是说,C库将检查内核空间的返回值,并根据该值设置errno. (注意,errno在用户空间中,而内核不知道它.)

比方说,如果syscall foo(),从用户的视图,在失败时返回-1并且应该设置errno以指示错误(ERR1表示失败1,ERR2表示失败2等),内核系统调用实现将返回-ERR1或-ERR2因此,C库将检查返回值是否为零,如果它为负,它将返回-1给用户,并将errno设置为ERR1 / ERR2.

希望这可以帮助.

更新:我检查了glibc的x86_64代码,这可能有助于理解这一点:

.text

ENTRY (syscall)

movq %rdi, %rax /* Syscall number -> rax. */

movq %rsi, %rdi /* shift arg1 - arg5. */

movq %rdx, %rsi

movq %rcx, %rdx

movq %r8, %r10

movq %r9, %r8

movq 8(%rsp),%r9 /* arg6 is on the stack. */

syscall /* Do the system call. */

cmpq $-4095, %rax /* Check %rax for error. */

jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */

L(pseudo_end):

ret /* Return to caller. */

PSEUDO_END (syscall)

File: "sysdeps/unix/sysv/linux/x86_64/syscall.S"

Linus说他将确保no syscall返回-1 .. -4095中的值作为有效结果,因此我们可以使用-4095进行保存测试.

更新:所以我猜你的c库转换了返回值.您的平台ABI可能会定义syscall在失败时返回{-1,-256},因此C包装器在这种情况下将返回值设置为-1并相应地设置errno.

标签:linux,system-calls,kernel

来源: https://codeday.me/bug/20190728/1565595.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值