简体   繁体   English

Fork系统调用失败后,rax中的返回值是多少?

[英]What is the return value in rax after a failed Fork syscall?

I know that calling fork() in C will return -1 if there is an error, but I'm wondering what the error return value is when you call sys_fork in assembly. 我知道如果有错误,在C中调用fork()会返回-1,但是我想知道在汇编中调用sys_fork时错误返回值是多少。

I might normally assume that it also returns -1 but I've dealt with sys_brk and the raw syscall in assembly returns something different from the C Brk() wrapper. 我通常可以假设它也返回-1,但是我已经处理过sys_brk,而汇编中的原始syscall返回的内容与C Brk()包装器有所不同。

Does anyone know what the fork error return value would be in assembly? 有谁知道汇编中的fork错误返回值是什么?

(I'm doing 64 bit NASM assembly on Linux) (我正在Linux上进行64位NASM组装)

First and foremost note that the C library wrapper fork(2) invokes sys_clone and not sys_fork . 首先注意,在C库包装fork(2)调用sys_clone和不sys_fork

C library/kernel differences C库/内核差异

Since version 2.3.3, rather than invoking the kernel's fork() system 从2.3.3版开始,而不是调用内核的fork()系统
call, the glibc fork() wrapper that is provided as part of the NPTL 调用,作为NPTL的一部分提供的glibc fork()包装器
threading implementation invokes clone(2) with flags that provide the 线程实现调用带有提供以下内容的标志的clone(2):
same effect as the traditional system call. 与传统系统调用效果相同。


The introduction to the section 2 of the Linux manual explains how to interpret the return value of a system call in a general context: Linux手册第2节简介介绍了如何在一般情况下解释系统调用的返回值:

RETURN VALUE 返回值

On error, most system calls return a negative error number (ie, the 发生错误时,大多数系统调用都会返回负错误号 (即
negated value of one of the constants described in errno(3)). errno(3)中描述的常数之一的取反值。 The C C
library wrapper hides this detail from the caller: when a system call 库包装程序向调用方隐藏了此详细信息:系统调用时
returns a negative value, the wrapper copies the absolute value into 返回负值,包装器将绝对值复制到
the errno variable, and returns -1 as the return value of the errno变量,并返回-1作为该变量的返回值
wrapper. 包装。

So for most system calls, EAX/RAX holds -ESOMETHING on error, or a non-negative result on success. 因此,对于大多数系统调用,EAX / RAX -ESOMETHING在错误时保留-ESOMETHING ,或者在成功时保留非负结果。 The libc wrappers decode this to implement the errno-setting and returning -1 behaviour described in the section 2 man pages, which primarily document the wrappers; libc包装器对此进行解码,以实现第2节手册中描述的errno设置和返回-1行为,这些手册主要记录了包装器; "C library/kernel differences" details are sometimes found in the Notes section of Linux man pages. 有时会在Linux手册页的“注释”部分中找到“ C库/内核差异”的详细信息。

It's important to note that this applies to most but not all system calls, as the first paragraph says. 重要的是要注意,正如第一段所述,这适用于大多数但并非所有系统调用。 sys_fork is not special in this regard. sys_fork在这方面并不特殊。 A couple interesting special cases are getpriority as mentioned in the beginning of errno(3) more below , and mmap . 一对夫妇有趣的特殊情况是getpriority在开头提到的errno(3) 更下方mmap (Valid pointers can have their high bit set, so distinguishing error from success requires other tricks, like checking the low bits since a successful mmap always returns a page-aligned address .) These ABI details are not documented in the man pages. (有效的指针可以将其高位设置为1,因此,将错误与成功区分开来还需要其他技巧, 例如检查低位,因为成功的mmap总是返回页面对齐的地址 。)这些ABI详细信息未在手册页中记录。


For the purpose of finding out if the sys_fork call was successful, testing for a negative value is enough: 为了找出sys_fork调用是否成功,测试一个负值就足够了:

test eax, eax
jl _error_handler              ;See Peter Cordes's comments below

I've included the part about the C library wrappers like fork(2) because it gives a practical method to find out the error numbers. 我包括了有关C库包装程序的部分,例如fork(2)因为它提供了一种实用的方法来找出错误号。
The value of errno , negated, are the possible error values the system call can return. 否定的errno值是系统调用可以返回的可能的错误值。

EAGAIN EAGAIN
ENOMEM ENOMEM
ENOSYS ENOSYS
ERESTARTNOINTR ERESTARTNOINTR

In general, the C library wrapper can add, remove or transcode the return values before writing them into errno , so this is failable. 通常,C库包装器可以在将返回值写入errno之前对其进行添加,删除或转码,因此这是失败的。

The definitive way to find out the possible return values is looking at the source. 确定可能的返回值的最终方法是查看源。
For example, do_fork , invoked by sys_fork , can return EINVAL and EPERM in addition to the values listed above. 例如,由sys_fork调用的do_fork除了上面列出的值之外,还可以返回EINVALEPERM
Other values are possible, I haven't dug into all the nested function calls. 其他值也是可能的,我还没有深入研究所有嵌套函数调用。

sys_clone also invokes do_fork so I would assume that clone(2) can return all of the error numbers that fork(2) can. sys_clone还调用do_fork因此我假设clone(2)可以返回fork(2)可以的所有错误号。


Investigating the case of sys_getpriority mentioned above a comment came up 在调查上述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.
 */

So it seems that Linux system calls always return negative values on an error, the C library wrappers than, in an attempt to normalise these values into errno , introduce an extra layer of complexity. 因此,似乎Linux系统调用总是在出错时返回负值,而C库包装程序则试图将这些值归一化为errno ,从而引入了额外的复杂性。

As we see from the mmap case, having the sign bit set doesn't always mean it's an error value. mmap情况可以看出,设置符号位并不总是意味着它是一个错误值。 According to this answer (merit goes to Peter Cordes comment below), values in the range [-4095, -1] always mean error, but other negative values should not. 根据此答案 (值得彼得·科德斯评论),范围[-4095,-1]中的值始终表示错误,而其他负值则不应。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM