2015-08-21 109 views
2

我正在使用定制的内核字符设备,它有时会为其ioctl()返回大的负值(大约为数千,说-2000)。Linux ioctl返回值由谁解释?

在用户空间中,我没有从ioctl调用返回这些值。相反,我得到的返回值为-1,errno设置为来自内核模块(+2000)的否定值。

据我可以读和谷歌,__syscall_return()是应该将负面的返回值解释为错误的宏。但是,它似乎只是查找-1到-125之间的值。所以我没有想到要翻译这些大的负面价值。

这些返回值在哪里翻译?它预期的行为?

我在Linux 2.6.35.10上使用EGLIBC 2.11.3-4 + deb6u6。

+1

有人可以将此问题迁移到SO吗? –

回答

2

翻译并移至errno发生在libc级别。同时提供了GNU libc和μClibc治疗负数到至少-4095错误条件,每http://www.makelinux.net/ldd3/chp-6-sect-1

对GNU libc实施ioctlhttps://github.molgen.mpg.de/git-mirror/glibc/blob/85b290451e4d3ab460a57f1c5966c5827ca807ca/sysdeps/unix/sysv/linux/aarch64/ioctl.S

+0

谢谢。我正在寻找i386的等价物,但无法找到它。你能帮忙吗? –

+0

我发现https://github.molgen.mpg.de/git-mirror/glibc/blob/85b290451e4d3ab460a57f1c5966c5827ca807ca/sysdeps/unix/sysv/linux/i386/syscall.S这似乎是做错误检查386。 –

0

所以,在BRPocock的帮助下,我会在这里汇报我的发现。

Linux内核会为沿线的所有的系统调用一个错误检查(从unistd.h):

#define __syscall_return(type, res) \ 
do { \ 
     if ((unsigned long)(res) >= (unsigned long)(-125)) { \ 
       errno = -(res); \ 
       res = -1; \ 
     } \ 
     return (type) (res); \ 
} while (0) 

libc库也将做沿(从syscall.S)的行所有的系统调用错误检查:

.text 
ENTRY (syscall) 

    PUSHARGS_6  /* Save register contents. */ 
    _DOARGS_6(44)  /* Load arguments. */ 
    movl 20(%esp), %eax /* Load syscall number into %eax. */ 
    ENTER_KERNEL  /* Do the system call. */ 
    POPARGS_6  /* Restore register contents. */ 
    cmpl $-4095, %eax /* Check %eax for error. */ 
    jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ 
    ret   /* Return to caller. */ 

PSEUDO_END (syscall) 

的Glibc给出了4096值的原因(来自sysdep.h):

/* Linux uses a negative return value to indicate syscall errors, 
unlike most Unices, which use the condition codes' carry flag. 
Since version 2.1 the return value of a system call might be 
negative even if the call succeeded. E.g., the `lseek' system call 
might return a large offset. Therefore we must not anymore test 
for < 0, but test for a real error by making sure the value in %eax 
is a real error number. Linus said he will make sure the no syscall 
returns a value in -1 .. -4095 as a valid result so we can savely 
test with -4095. */ 

__syscall_return似乎从新内核中丢失了,我还没有研究过。