我知道如果出现错误,在C中调用fork()
将返回-1,但我想知道在程序集中调用sys_fork
时错误返回值是什么。
我通常会假设它也返回-1但是我已经处理了sys_brk并且程序集中的原始系统调用返回了与C Brk()包装器不同的东西。
有没有人知道汇编中的fork错误返回值是什么?
(我在Linux上进行64位NASM汇编)
答案 0 :(得分:3)
首先请注意,C库包装器fork(2)
调用sys_clone
而非sys_fork
。
C库/内核差异
从版本2.3.3开始,而不是调用内核的fork()系统
调用,作为NPTL的一部分提供的glibc fork()包装器 线程实现使用提供
的标志调用clone(2) 与传统系统调用相同的效果。
introduction to the section 2 of the Linux manual解释了如何在一般上下文中解释系统调用的返回值:
返回值
出错时,大多数系统调用都会返回负数错误号(即, 否定了errno(3)中描述的常量之一的值。 C
库包装器从调用者隐藏这个细节:当系统调用时 返回负值,包装将绝对值复制到
errno变量,并返回-1 作为
的返回值 包装
因此,对于大多数系统调用,EAX / RAX在出错时保持-ESOMETHING
,或在成功时保持非负结果。 libc包装器对此进行解码,以实现第2节手册页中描述的errno设置和返回-1行为,该手册主要记录包装器; " C库/内核差异"有时会在Linux手册页的Notes部分找到详细信息。
重要的是要注意,这适用于大多数但不是所有系统调用,如第一段所述。 sys_fork
在这方面并不特别。一些有趣的特殊情况是getpriority
,如errno(3)
更多以及mmap
的开头所述。 (有效指针可以设置高位,因此区别错误与成功需要其他技巧like checking the low bits since a successful mmap always returns a page-aligned address。)这些ABI详细信息未在手册页中记录。
为了找出sys_fork
电话是否成功,测试负值就足够了:
test eax, eax
jl _error_handler ;See Peter Cordes's comments below
我已经包含了关于像fork(2)
这样的C库包装器的部分,因为它提供了一种找出错误编号的实用方法。
errno
的值,否定,是系统调用可以返回的可能错误值。
EAGAIN
ENOMEM
ENOSYS
ERESTARTNOINTR
通常,C库包装器可以在将返回值写入errno
之前添加,删除或转码它们,因此这是可用的。
找出可能的回报值的明确方法是查看来源
例如,由sys_fork
调用的do_fork
除了上面列出的值外,还可以返回EINVAL
和EPERM
。
其他值是可能的,我没有挖到所有嵌套函数调用。
sys_clone
也会调用do_fork
所以我会假设
clone(2)
可以返回fork(2)
可以包含的所有错误号。
对上述sys_getpriority
的案例进行调查后出现了评论
/*
* Ugh. To avoid negative return values, "getpriority()" will
* not return the normal nice-value, but a negated value that
* has been offset by 20 (ie it returns 40..1 instead of -20..19)
* to stay compatible.
*/
所以似乎Linux系统调用总是在错误上返回负值,C库包装器,为了将这些值规范化为errno
,引入了额外的一层复杂性。
正如我们从mmap
案例中看到的那样,设置符号位并不总是意味着它是一个错误值。
根据{{3}}(下面的Peter Cordes评论的优点), [ - 4095,-1] 范围内的值始终表示错误,但其他负值不应该。