Assembly 中系统调用的 return 值是多少?
What are the return values of system calls in Assembly?
当我尝试研究内核系统调用的 return 值时,我找到了描述它们的表格以及我需要在不同的寄存器中放入什么才能让它们工作。但是,我没有找到任何文档说明 what 是我从系统调用中获得的 return 值。我只是在不同的地方发现我收到的内容会在 EAX 寄存器中。
The result is usually returned in the EAX register.
Assembly Language Step-By-Step: Programming with Linux Jeff Duntemann 的书在他的程序中多次提到:
Look at sys_read's return value in EAX
Copy sys_read return value for safe keeping
我的任何网站都没有解释这个 return 值。有没有互联网资源?或者有人可以向我解释一下这个值吗?
另请参阅 this excellent LWN article about system calls,其中假设 C 知识。
另外:The Definitive Guide to Linux System Calls (on x86), and related: What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?
C 是 Unix 系统编程的语言,所以所有的文档都是关于 C 的。然后在任何给定平台上都有关于 C 接口和 asm 之间的细微差别的文档,通常在注释部分手册页。
sys_read
表示原始系统调用(相对于 libc 包装函数)。 read
系统调用的内核实现是一个名为 sys_read()
的内核函数。你不能用 call
指令调用它,因为它在内核中,而不是库中。但是人们还是说“调用sys_read
”来区别于libc函数调用。但是,即使您指的是原始系统调用(尤其是当 libc 包装器没有做任何特别的事情时),也可以说 read
,就像我在这个答案中所做的那样。
另请注意,syscall.h
定义常量,如 SYS_read
与实际系统调用号,或 asm/unistd.h
用于 Linux __NR_read
相同的名称常数。 (您在 int 0x80
或 syscall
指令之前放入 EAX 的值)。
Linux 系统调用 return 值(在 x86 上的 EAX
/RAX
中)要么是“正常”成功,要么是 -errno
code for error. e.g. -EFAULT
if you pass an invalid pointer. This behaviour is documented in the syscalls(2)
手册页.
-1 到-4095 表示错误,其他任何表示成功。有关此 -4095UL .. -1UL
范围的更多详细信息,请参阅 AOSP non-obvious syscall() implementation,它可在 Linux 上跨体系结构移植,并适用于 every 系统调用。 (在未来,不同的体系结构可以为 MAX_ERRNO 使用不同的值,但是像 x86-64 这样的现有架构的值保证与 Linus 的 don't-break-userspace 保持不变的一部分政策保持一致内核 ABI 稳定。)
例如,glibc 的 generic syscall(2)
wrapper function uses this sequence: cmp rax, -4095
/ jae SYSCALL_ERROR_LABEL
, which is guaranteed to be future-proof 用于所有 Linux 系统调用。
您可以使用该包装函数进行任何系统调用,例如 syscall( __NR_mmap, ... )
。 (或者使用像 https://github.com/linux-on-ibm-z/linux-syscall-support/blob/master/linux_syscall_support.h 这样的 inline-asm 包装器 header ,它对多个 ISA 具有安全 inline-asm ,避免像丢失 "memory"
clobbers 这样的问题,其他 inline-asm包装纸有。)
有趣的案例包括 getpriority
,其中内核 ABI 将 -20..19 return-value 范围映射到 1..40,而 libc 对其进行解码。 a related answer about decoding syscall error return values.
中有更多详细信息
对于 mmap,如果您愿意,您也可以通过检查 return 值不是 page-aligned 来检测错误(例如,低 11 位中的任何 non-zero 位,对于4k 页面大小),如果这比检查 p > -4096ULL
.
更有效的话
要查找特定平台常量的实际数值,您需要在 #define
d 中找到 C header 文件。有关详细信息,请参阅 my answer on a question about that。例如在 asm-generic/errno-base.h
/ asm-generic/errno.h
.
每个系统调用的 return 值的含义记录在第 2 部分手册页中,例如 read(2)
。 (sys_read
是原始系统调用,glibc read()
函数是一个非常薄的包装器。)大多数手册页都有一个完整的部分用于 return 值。例如
RETURN VALUE
On success, the number of bytes read is returned (zero indicates
end of file), and the file position is advanced by this number. It
is not an error if this number is smaller than the number of bytes
requested; this may happen for example because fewer bytes are
actually available right now (maybe because we were close to end-of-
file, or because we are reading from a pipe, or from a terminal), or
because read() was interrupted by a signal. See also NOTES.
On error, -1 is returned, and errno is set appropriately. In this
case, it is left unspecified whether the file position (if any)
changes.
请注意,如果原始系统调用的 return 值为负,最后一段描述了 glibc 包装器如何将值和 sets errno 解码为 -EAX
,因此 errno=EFAULT
和 return -1
如果原始系统调用 returned -EFAULT
.
还有一个完整的部分列出了 read()
允许 return 的所有可能的错误代码,以及它们对 read()
的具体含义。 (POSIX 标准化了大部分这种行为。)
当我尝试研究内核系统调用的 return 值时,我找到了描述它们的表格以及我需要在不同的寄存器中放入什么才能让它们工作。但是,我没有找到任何文档说明 what 是我从系统调用中获得的 return 值。我只是在不同的地方发现我收到的内容会在 EAX 寄存器中。
The result is usually returned in the EAX register.
Assembly Language Step-By-Step: Programming with Linux Jeff Duntemann 的书在他的程序中多次提到:
Look at sys_read's return value in EAX
Copy sys_read return value for safe keeping
我的任何网站都没有解释这个 return 值。有没有互联网资源?或者有人可以向我解释一下这个值吗?
另请参阅 this excellent LWN article about system calls,其中假设 C 知识。
另外:The Definitive Guide to Linux System Calls (on x86), and related: What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?
C 是 Unix 系统编程的语言,所以所有的文档都是关于 C 的。然后在任何给定平台上都有关于 C 接口和 asm 之间的细微差别的文档,通常在注释部分手册页。
sys_read
表示原始系统调用(相对于 libc 包装函数)。 read
系统调用的内核实现是一个名为 sys_read()
的内核函数。你不能用 call
指令调用它,因为它在内核中,而不是库中。但是人们还是说“调用sys_read
”来区别于libc函数调用。但是,即使您指的是原始系统调用(尤其是当 libc 包装器没有做任何特别的事情时),也可以说 read
,就像我在这个答案中所做的那样。
另请注意,syscall.h
定义常量,如 SYS_read
与实际系统调用号,或 asm/unistd.h
用于 Linux __NR_read
相同的名称常数。 (您在 int 0x80
或 syscall
指令之前放入 EAX 的值)。
Linux 系统调用 return 值(在 x86 上的 EAX
/RAX
中)要么是“正常”成功,要么是 -errno
code for error. e.g. -EFAULT
if you pass an invalid pointer. This behaviour is documented in the syscalls(2)
手册页.
-1 到-4095 表示错误,其他任何表示成功。有关此 -4095UL .. -1UL
范围的更多详细信息,请参阅 AOSP non-obvious syscall() implementation,它可在 Linux 上跨体系结构移植,并适用于 every 系统调用。 (在未来,不同的体系结构可以为 MAX_ERRNO 使用不同的值,但是像 x86-64 这样的现有架构的值保证与 Linus 的 don't-break-userspace 保持不变的一部分政策保持一致内核 ABI 稳定。)
例如,glibc 的 generic syscall(2)
wrapper function uses this sequence: cmp rax, -4095
/ jae SYSCALL_ERROR_LABEL
, which is guaranteed to be future-proof 用于所有 Linux 系统调用。
您可以使用该包装函数进行任何系统调用,例如 syscall( __NR_mmap, ... )
。 (或者使用像 https://github.com/linux-on-ibm-z/linux-syscall-support/blob/master/linux_syscall_support.h 这样的 inline-asm 包装器 header ,它对多个 ISA 具有安全 inline-asm ,避免像丢失 "memory"
clobbers 这样的问题,其他 inline-asm包装纸有。)
有趣的案例包括 getpriority
,其中内核 ABI 将 -20..19 return-value 范围映射到 1..40,而 libc 对其进行解码。 a related answer about decoding syscall error return values.
对于 mmap,如果您愿意,您也可以通过检查 return 值不是 page-aligned 来检测错误(例如,低 11 位中的任何 non-zero 位,对于4k 页面大小),如果这比检查 p > -4096ULL
.
要查找特定平台常量的实际数值,您需要在 #define
d 中找到 C header 文件。有关详细信息,请参阅 my answer on a question about that。例如在 asm-generic/errno-base.h
/ asm-generic/errno.h
.
每个系统调用的 return 值的含义记录在第 2 部分手册页中,例如 read(2)
。 (sys_read
是原始系统调用,glibc read()
函数是一个非常薄的包装器。)大多数手册页都有一个完整的部分用于 return 值。例如
RETURN VALUE
On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number. It is not an error if this number is smaller than the number of bytes requested; this may happen for example because fewer bytes are
actually available right now (maybe because we were close to end-of-
file, or because we are reading from a pipe, or from a terminal), or
because read() was interrupted by a signal. See also NOTES.On error, -1 is returned, and errno is set appropriately. In this case, it is left unspecified whether the file position (if any)
changes.
请注意,如果原始系统调用的 return 值为负,最后一段描述了 glibc 包装器如何将值和 sets errno 解码为 -EAX
,因此 errno=EFAULT
和 return -1
如果原始系统调用 returned -EFAULT
.
还有一个完整的部分列出了 read()
允许 return 的所有可能的错误代码,以及它们对 read()
的具体含义。 (POSIX 标准化了大部分这种行为。)