Linux ioctl返回值由谁解释?

时间:2015-08-21 15:01:35

标签: ioctl

我正在使用自定义内核字符设备,它有时会为其ioctl()返回大的负值(大约数千,比如-2000)。

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

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

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

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

2 个答案:

答案 0 :(得分:2)

翻译并移至errnolibc。根据{{​​3}}

错误条件,Gnu libc和μClibc都将负数降低至至少-4095

有关libc的Gnu ioctl实施内容,请参见http://www.makelinux.net/ldd3/chp-6-sect-1

答案 1 :(得分: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,我还没有研究过。