为什么 glibc 将系统调用的 return 值存储到 errno 中
Why does glibc store the return value of a system call into errno
我读到当系统调用失败时内核 returns 解释失败的相应错误号。为什么这个错误不直接返回给用户应用程序?
为什么 glibc 将其存储在全局 errno
变量中?这样做有什么好处?
正在将评论转为答案。
errno
的使用是争论的主题,但归结为 "historical reasons"。早期版本的 Unix 做到了——后来的版本(以及标准 C 和 POSIX)都保留它以避免破坏工作代码。 errno
机制有很多缺陷,尤其是在现代多线程代码中。 POSIX pthread 库不使用 errno
;函数直接报告错误号。您可以在 P J Plauger The Standard C Library (1992) 等书中找到对 errno
的诽谤。它已经很老了,描述了 C90,但其中大部分内容在今天仍然适用。
Error Numbers 上的 POSIX 基本原理有很多关于该主题的信息。请特别注意 'Alternative Solutions for Per-Thread errno
'.
小节
请注意,旧的 C 代码可能会在源文件中写入 extern int errno;
。由于多线程变得司空见惯,这是不正确的。在现代代码中获得 errno
声明的唯一正确方法是 #include <errno.h>
。这是因为名称可能是 'modifiable lvalue' 的宏。在一个系统(macOS Catalina 10.15.2)上,您可以找到:
extern int * __error(void); // Do not copy this
#define errno (*__error()) // Do not copy this
这与 extern int errno;
完全不同。请注意,其他系统有不同的声明方式——您不能将我展示的内容复制到您的代码中并期望它能正常工作。包括 header;它简单可靠(并且是可靠地完成工作的唯一方法)。
我读到当系统调用失败时内核 returns 解释失败的相应错误号。为什么这个错误不直接返回给用户应用程序?
为什么 glibc 将其存储在全局 errno
变量中?这样做有什么好处?
正在将评论转为答案。
errno
的使用是争论的主题,但归结为 "historical reasons"。早期版本的 Unix 做到了——后来的版本(以及标准 C 和 POSIX)都保留它以避免破坏工作代码。 errno
机制有很多缺陷,尤其是在现代多线程代码中。 POSIX pthread 库不使用 errno
;函数直接报告错误号。您可以在 P J Plauger The Standard C Library (1992) 等书中找到对 errno
的诽谤。它已经很老了,描述了 C90,但其中大部分内容在今天仍然适用。
Error Numbers 上的 POSIX 基本原理有很多关于该主题的信息。请特别注意 'Alternative Solutions for Per-Thread errno
'.
请注意,旧的 C 代码可能会在源文件中写入 extern int errno;
。由于多线程变得司空见惯,这是不正确的。在现代代码中获得 errno
声明的唯一正确方法是 #include <errno.h>
。这是因为名称可能是 'modifiable lvalue' 的宏。在一个系统(macOS Catalina 10.15.2)上,您可以找到:
extern int * __error(void); // Do not copy this
#define errno (*__error()) // Do not copy this
这与 extern int errno;
完全不同。请注意,其他系统有不同的声明方式——您不能将我展示的内容复制到您的代码中并期望它能正常工作。包括 header;它简单可靠(并且是可靠地完成工作的唯一方法)。