刚接触到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.
#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;
}
#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




