2016-08-03 87 views
2

当我尝试研究内核系统调用的返回值时,我找到描述它们的表以及我需要放入不同的寄存器以让它们工作的表。然而,我没有找到任何文件,它说什么是我从系统调用返回的值。我只是在不同的地方发现,我收到的将会在EAX寄存器中。汇编中系统调用的返回值是什么?


TutorialsPoint

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

汇编语言步骤一步:由杰夫Duntemann的Linux书编程在他的计划指出很多次:

  • 看SYS_READ的返回值在EAX

  • 复制sys_read的安全保存返回值


任何网站我有没有这个返回值说明的。有没有互联网来源?或者有人可以向我解释这个价值吗?

+0

尝试使用Google搜索“sys_read”。这是我发现的东西。 http://asm.sourceforge.net/syscall.html –

+0

@MarkLakata我试过但没有帮助。正如我所说的,它只是说我需要在不同的寄存器中放入什么,以便系统调用起作用。 (例如[here](http://docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.html)和[here](http://blog.rchapman.org/post/36801038863/linux -system-call-table-for-x86-64)。) –

+1

如果你的谷歌“sys_read”的第四个链接是这样的:https://lwn.net/Articles/604287/,它有所有的血淋淋的细节。 –

回答

5

另请参阅this excellent LWN article about system calls它承担C知识。

另外:The Definitive Guide to Linux System Calls (on x86),以及相关:What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?


C是Unix系统的编程语言,因此,所有的文档都以C的条款,然后在那里C接口之间的细微差别的文档和任何给定平台上的asm,通常在手册页的Notes部分。

sys_read表示原始系统调用(与libc包装函数相反)。 read系统调用的内核实现是一个称为sys_read()的内核函数。你不能用call指令调用它,因为它在内核中,而不是在库中。但人们仍然在谈论“调用sys_read”以区别于libc函数调用。然而,即使你的意思是原始的系统调用(特别是当libc包装器没有做任何特别的事情时),也可以说read,就像我在这个答案中做的那样。

另请注意,syscall.h定义了常量,如SYS_read与实际系统呼叫号码。 (您在int 0x80syscall指令之前放入EAX的值)。


Linux系统调用的返回值(在EAX在x86/RAX)或者是成功的非负值,或a negative error code。例如如果您传递了无效指针,则为-EFAULT

此行为记录在syscalls(2)手册页中。

实际上,-1到-4095意味着错误,其他意味着成功。 glibc的generic syscall(2) wrapper使用这个序列:cmp rax, -4095/jae SYSCALL_ERROR_LABEL,对于所有的Linux系统调用显然是guaranteed to be future-proof。有趣的案例包括mmap,其中有效地址为can have the sign bit set, but must be page alignedgetpriority,其中内核ABI将-20..19的返回值范围映射到1..40,并由libc对其进行解码。更多详情请参阅a related answer about decoding syscall error return values

更新,是它绝对保证所有系统调用-4095 .. -1是Linux运行的所有体系结构上的错误范围。有关更多详细信息,请参阅AOSP non-obvious syscall() implementation。 (将来,不同的体系结构可以为MAX_ERRNO使用不同的值,但现有的像x86-64这样的拱的值可以保持不变,这是Linux保持内核ABI稳定的不间断用户空间策略的一部分。 )


要找到常量的实际数值为特定的平台,你需要找到C头文件,他们是#define d。详情请参阅my answer on a question about that


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

返回值

成功时,字节读取返回的个数(零表示文件的结束 ),并且该文件的位置由该数目提前。如果这个数字小于请求的字节数 ,则它不是错误;这可能会发生,例如因为更少的字节实际上现在可用(可能是因为我们接近
文件,或者因为我们正在从管道或终端读取)或
因为读取()被一个信号中断。另请参阅注释。

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

需要注意的是最后一段描述glibc的包装如果原始系统调用的返回值是负数如何解码值和sets errno-EAX,所以errno=EFAULT并返回-1如果原始系统调用返回-EFAULT

还有一整段列出了允许read()返回的所有可能的错误代码,以及它们专门用于read()的含义。 (POSIX将这种行为的大部分标准化。)


我不知道究竟在何处的glibc解码返回值mmap(2),这里的返回值不是一个符号类型。它可能使用与通用的系统调用封装器相同的方法(检查无符号值> -4096UL),但每个系统调用的特定封装器没有实际混洗寄存器之间的参数和调用该函数的开销。

我没有看到它in the glibc source tree;据推测它被埋在了一些宏的层次之下。例如in the x86-64 macro

+0

1. * sys_read *等于'read()'吗? 2.什么是'-errno','-EFAULT'和'-retval'?它与Assembly有什么关系? –

+1

@PichiWuana:1.当然可以。 2. C是Unix系统编程的语言。所有内容都以C语言记录。 C基本上就是便携式汇编语言。 ['errno'是一个全局](http://man7.org/linux/man-pages/man3/errno.3.html),它是在任何库函数遇到错误后设置的。 '-'是C一元否定运算符。 'EFAULT'是一个由C预处理器宏定义的整数常量。 'retval'是我编写的一个变量名,用于描述EAX在系统调用后保留的内容。 –

+0

这是否意味着如果你知道好的汇编程序设计,你会很容易地理解C语言?反之亦然? –