繁体   English   中英

为什么errno,当POSIX函数通过返回-1或NULL指示错误条件时

[英]Why errno, when POSIX function indicate error condition by returning -1 or NULL

当其中一个UNIX系统函数发生错误时,通常会返回负值,并将整数errno设置为一个值,从而提供其他信息。 - UNIX环境中的高级编程,第1.7节

这看起来很奇怪:

  • 它引入了标准库的不同编译单元之间的耦合 - 错误状态未在导致它们的模块中定义。
  • 它引入了实现复杂性,因为errno需要是线程本地的。
  • 它引入了可用性复杂性,因为用户需要检查原始系统调用是否有错误,然后检查errno哪个也是另一个函数调用。

为什么不在返回值中编码错误状态?

主要由于历史原因。

请注意,实际上, errno今天不是普通的全局变量(在20世纪80年代就是这种情况)。 这是今天(C99,C11 ...)宏-通常是扩展到一些函数调用,或许__errno()和最近的C标准要求 errno是一个宏,见n1570第7.5节); 或者它可能会扩展到一些线程局部变量,甚至一些编译器魔法。

errno希望成为多线程需求的宏,所以我猜这些标准发展到要求它成为一些宏

所以你应该#include <errno.h>并使用errno宏,就好像它是一个全局变量,但知道它实际上不是一个。

细节是特定于实现的。 查看C标准库的源代码,例如musl-libcerrno / __ errno_location.c中

  int *__errno_location(void)
  {
     return &__pthread_self()->errno_val;
  }

并在include / errno.h公共标题中:

 int *__errno_location(void);
 #define errno (*__errno_location())

和GNU libc有一些非常相似的东西

BTW一些​​系统函数不返回整数(例如mmap ),并且一些POSIX函数不指示错误通过errno ,例如dlopen (参见dlerror )。 因此,在某些标准中很难保证每个错误都可以由返回值指示。

我会引用Linus Torvalds的话。

“错误号”在UNIX那几个非常糟糕愚蠢的一个。 Linux修复了它,并没有在内部使用它,也永远不会。 太糟糕了,用户空间必须修复返回内核所做的正确错误代码,并将其转换为“errno”愚蠢以实现向后兼容性。

[...]

“errno”是那些根本不应该存在的破碎事物之一。 原来的UNIX是错的,现在错了。

[...]

Linux返回负错误号的方法要好得多。 它本质上是线程安全的,并没有性能缺点。 当然,它确实依赖于拥有足够的结果域,您可以始终将错误返回与良好的返回分开,但在实践中对所有系统调用都是如此。

暂无
暂无

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

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