xixitalk's snippet

Post Longer Than 140 Characters Tweets

Aug 2, 2018 - Comments

标准C库里的errno是怎么实现的?

首先errno是个全局变量,刚开始UNIX/Linux只有进程,这样多进程也是安全的。但是后来有了线程,线程间是可以共享全局变量的,这样errno就线程不安全了。解决办法是线程实现TLS(Thread Local Storage),每个线程都有一个errno变量。

errno is defined by the ISO C standard to be a modifiable lvalue of type int, and must not be explicitly declared; errno may be a macro. errno is thread-local; setting it in one thread does not affect its value in any other thread.

如uClibc里的定义./libc/misc/internals/errno.c,glibc是csu/errno.c

	__thread int errno;

这依赖编译器打开TLS特性,很多嵌入式编译链不一定打开。运行arm-linux-uclibcgnueabi-gcc -v来检查,如果看到--enable-tls就是编译链打开TLS特性,这样编译链支持__thread或者thread_local关键词。

如果是C库是可配置的,C库的TLS也要打开,如uClibc,查看include/bits/uClibc_config.h文件,查找是否有下面选项:

#define __UCLIBC_HAS_TLS__ y

参考资料

  1. Is errno thread-safe?
  2. Thread_Local_Storage

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。