Jul 27

全局变量errno: Thread-Local Storage 不指定

felix021 @ 2010-7-27 22:50 [IT » 操作系统] 评论(2) , 引用(0) , 阅读(15098) | Via 本站原创 | |
在ISO C规范中有有一个很诡异的东西,那就是传说中的errno,一个有左值的int。当库函数出错的时候,它很可能会被设置为非0值;且没有任何一个库函数或系统调用会把它置为0。

刚接触到errno,可能会认为这是个在errno.h中用
int errno;
定义的整型。但是一旦开始写多线程的程序,再看到errno的时候,就会抑郁了。如果两个线程调用库函数都出错,那errno怎么办...?

幸而,ISO C并没有规定,errno必须是一个int,如果看errno的manpage (man errno) 会看到:
引用
errno may be a macro.  errno is thread-local; setting it in one thread does not affect its value in any other thread.
实际上GNU的glibc也就是这么实现的,(通常)在/usr/include/bits/errno.h里头:
#define errno (*__errno_location ())

于是errno就是个有左值的int了。至于这个__errno_location,在glibc的源码的 csu/errno-loc.c 里头:
int *
#if ! USE___THREAD
weak_const_function
#endif
__errno_location (void)                                                                                                                                     
{
  return &errno;
}

而这里的真正的errno,在 csu/errno.c 里头:
__thread int errno;

由于包含的都是errno.h,所以对于用户程序而言,可见的只有errno.h中的"errno",实际上是(*(__errno_location()),而__errno_location()返回的是errno.c中的errno的地址。可真绕啊。可是偏偏又不能把 __thread int errno; 放在errno.h中,为什么呢?其实原因很简单也很复杂——C语言真是个纠结的语言。

最后,解释一下“__thread”修饰符:__thread defines number to be a thread local variable. 定义thread-local的变量。详情参见Thread-local_storage的wiki页:http://en.wikipedia.org/wiki/Thread-local_storage



欢迎扫码关注:




转载请注明出自 ,如是转载文则注明原出处,谢谢:)
RSS订阅地址: https://www.felix021.com/blog/feed.php
ddsadas
2017-12-14 13:58
smokeshockgrinfaintunhappyunhappysleepyfaint
sandy
2010-7-28 11:41
昨天我也在errno纠结了一下。
我写了这么个函数:
bool err_can_ignore(int errno)
{
//..
}
然后用的时候一直提示不能把int转换为int*(*)() ……

郁闷了好久,才想起这个errno,换了个名字,正常。同时顺便也就了解到了errno的本质……
分页: 1/1 第一页 1 最后页
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
记住我
昵称   密码   *非必须
网址   电邮   [注册]