11.4 返回值
如果系统调用没有返回一些数值, 那么在很多情况下并没有太多用处。这些返回值包括: 一个打开的文件的文件描述符、 一个从缓存里读取的字节, 或者系统时间等等。
此外, 如果错误出现, 系统需要通知我们。 这些错误包括: 文件不存在、系统资源耗尽,或者我们传递了一个错误的参数等等。
11.4.1 联机手册
传统情况下,寻找 UNIX® 下不同系统调用的地方是手册页。 FreeBSD 会在手册页的第2节描述系统调用,有的时候会在第三节。
例如, open(2) 所描述的:
如果执行成功,
open()
将返回一个表示文件描述符的非负整数。 如果执行失败, 它会返回-1
并且设置errno
来标识错误。
刚刚接触 UNIX 和 FreeBSD的汇编程序员或许会马上提出一个难题: 那些 errno
在哪里?我怎么才能找得到它们?
注意: 这些在手册页中展示的信息仅针对 C 语言。 汇编程序员则需要更多的信息。
11.4.2 返回值在哪里?
很不幸, 它有依赖性。。。 大部分系统调用都使用 EAX
但不是所有的系统调用都会这样。 不过当第一次使用系统调用的时候,直接在 EAX
检查返回值是个不错的查找方法。 如果它不在那里, 你再需要深入调查。
注意: 我知道一个
SYS_fork
的系统调用将返回值存放在EDX
中。而我曾经用过的其他调用都使用EAX
存放返回值, 但是我目前还没有用过所有的系统调用。
提示: 如果你哪里都找不到答案, 去学习 libc 代码吧,去看看它如何访问内核的。
11.4.3 哪里可以找到 errno
?
实际上,没什么地方。。。
errno
不属于 UNIX 内核, 而是 C 语言中的一部分。 当直接访问内核服务的时候, 错误代码返回到 EAX
中,也就是那个通常用来保存返回值得寄存器。
这个处理方式非常有意义。 如果这里没有错误, 这里就没有错误代码。 如果这里有错误,这里就没有返回值。 使用一个寄存器可以涵盖以上任意一种情况。
11.4.4 判断错误的出现
当使用标准的 FreeBSD 调用规范时,标志位 carry flag
在程序运行成功时被清零,在失败时被置位。
当使用 Linux emulation 模式的时候, EAX
中的有符号数反映了执行结果。 当为非负数时,表示执行成功, 并包含了返回值。 如果失败, 返回值即为负数, 如 -errno
。