Assembly中系统调用的返回值是什么



当我试图研究内核的系统调用的返回值时,我会找到描述它们的表,以及我需要在不同的寄存器中放入什么才能让它们工作。但是,我找不到任何文档说明我从系统调用中得到的返回值是什么。我只是在不同的地方发现,我收到的东西将在EAX寄存器中。


教程要点:

结果通常在EAX寄存器中返回。

汇编语言一步一步:用Linux编程Jeff Duntemann的书在他的程序中多次提到:

  • 查看EAX中sys_read的返回值

  • 复制sys_read返回值以进行安全保存


我拥有的任何一个网站都没有解释这个回报值。有网络资源吗?或者有人能向我解释一下这种价值观吗?

另请参阅这篇关于假定C知识的系统调用的优秀LWN文章。

还有:Linux系统调用最终指南(x86上)和相关内容:如果在64位代码中使用32位int 0x80 Linux ABI,会发生什么?


C是Unix系统编程的语言,所以所有的文档都是用C编写的。然后,在任何给定的平台上,都有关于C接口和asm之间微小差异的文档,通常在手册页的Notes部分。

sys_read表示原始系统调用(与libc包装函数相反)。read系统调用的内核实现是一个名为sys_read()的内核函数。不能用call指令调用它,因为它在内核中,而不是库中。但人们仍然在谈论";调用CCD_ 5";以将其与libc函数调用区分开来。然而,即使您指的是原始系统调用(尤其是当libc包装器没有做任何特殊的事情时),也可以说read,就像我在这个答案中所做的那样。

还要注意,syscall.h使用实际的系统调用号定义了SYS_read之类的常量,或者asm/unistd.h用于相同常量的Linux __NR_read名称。(在int 0x80syscall指令之前放入EAX中的值)。


Linux系统调用返回值(在x86上的EAX/RAX中)是"0"或"0";正常的";成功或错误的-errno代码。例如-EFAULT,如果您传递了一个无效指针。这种行为记录在syscalls(2)手册页中。

-1到-4095表示错误,其他任何值都表示成功。有关此-4095UL .. -1UL范围的更多详细信息,请参阅AOSP非显而易见的syscall()实现,它可在Linux上跨体系结构进行移植,并适用于每个系统调用。(未来,不同的体系结构可能会对MAX_ERRNO使用不同的值,但像x86-64这样的现有拱门的值保证保持不变,这是Linus保持内核ABI稳定的"不中断-用户空间"策略的一部分。)

例如,glibc的通用syscall(2)包装器函数使用以下序列:cmp rax, -4095/jae SYSCALL_ERROR_LABEL,它保证对所有Linux系统调用都是经得起未来考验的。

您可以使用该包装器函数进行任何系统调用,如syscall( __NR_mmap, ... )。(或者使用内联asm包装头,如https://github.com/linux-on-ibm-z/linux-syscall-support/blob/master/linux_syscall_support.h它为多个ISAs提供了安全的内联asm,避免了其他一些内联asm包装器所缺少的"memory" clobber等问题。)


有趣的例子包括getpriority,其中内核ABI将-20..19返回值范围映射到1..40,并由libc对其进行解码。有关解码系统调用错误返回值的详细信息,请参阅相关答案。

对于mmap,如果你愿意,你也可以通过检查返回值是否与页面对齐来检测错误(例如,对于4k页面大小,低11中的任何非零位),如果这比检查p > -4096ULL更有效的话。


要找到特定平台的常量的实际数值,您需要找到它们所在的C头文件#defined。有关详细信息,请参阅我对该问题的回答。例如在CCD_ 27/asm-generic/errno.h中。


每个sys调用的返回值的含义记录在第2节手册页中,如read(2)。(sys_read是原始系统调用,glibc read()函数是它的一个非常薄的包装器。)大多数手册页都有一整段返回值。例如

返回值

成功后,返回读取的字节数(零表示文件末尾),并且文件位置提前了这个数字。它如果此数字小于字节数,则不是错误请求;例如,这可能是因为
的字节数较少实际上现在可以使用(可能是因为我们即将结束-
文件,或者因为我们正在从管道或终端读取),或者
因为read()被一个信号中断。另请参见注释。

出现错误时,返回-1,并适当设置errno。在这个情况下,未指定文件位置(如果有)
更改。

请注意,最后一段描述了如果原始系统调用的返回值为负数,那么glibc包装器如何解码该值并将errno设置为-EAX,因此为errno=EFAULT,如果原始系统呼叫返回-EFAULT,则返回-1

还有一整节列出了read()可以返回的所有可能的错误代码,以及它们对read()的具体含义。(POSIX标准化了大部分这种行为。)

最新更新