Linux ioctl 返回值由谁解释?

Posted

技术标签:

【中文标题】Linux ioctl 返回值由谁解释?【英文标题】:Linux ioctl return value interpreted by who? 【发布时间】:2015-08-21 15:01:34 【问题描述】:

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

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

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

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

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

【问题讨论】:

有人可以将此问题迁移到 SO 吗? 【参考方案1】:

转换和移动到errno 发生在libc 级别。 Gnu libc 和 μClibc 都将负数降低到至少 -4095 作为错误条件,根据 http://www.makelinux.net/ldd3/chp-6-sect-1

请参阅 https://github.molgen.mpg.de/git-mirror/glibc/blob/85b290451e4d3ab460a57f1c5966c5827ca807ca/sysdeps/unix/sysv/linux/aarch64/ioctl.S 以了解 ioctl 的 Gnu libc 实现。

【讨论】:

谢谢。我正在寻找 i386 的等价物,但找不到。你能帮忙吗? 我发现github.molgen.mpg.de/git-mirror/glibc/blob/… 似乎对 386 进行了错误检查。【参考方案2】:

所以,在 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,我还没有研究过。

【讨论】:

以上是关于Linux ioctl 返回值由谁解释?的主要内容,如果未能解决你的问题,请参考以下文章

ioctl(sock, SIOCETHTOOL, &ifr) 为啥它总是返回-1

Ioctl返回-1的一个Bug查找

字符串函数---atof()函数具体解释及实现(完整版)

Linux下利用ioctl函数获取网卡信息

C语言试题八之计算下列级数和,和值由函数值返回 S=1+x+x^2/2! + x^3/3!+…x^n/n!

ethtool ioctl 返回未填充的 ethtool_link_settings