Linux 多线程编程问题 1 重入问题 传统的UNIX 没有太多考虑线程问题,库函数里过多使用了全局和静态数据,导致严重的线程重入问题
1 –D_REENTRANT /-pthread 和errno 的重入问题
所先 UNIX 的系统调用被设计为出错返回-1,把错误码放在 errno 中(更简单而直 接的方法应该是程序直接返回错误码,或者通过几个参数指针来返回)
由于线程 共享所有的数据区,而 errno 是一个全局的变量,这里产生了最糟糕的线程重入问 题
比如: do { bytes = recv(netfd, recvbuf, buflen, 0); } while (bytes
= -1 && errno
= EINTR); 在上面的处理 recv 被信号打断的程序里
如果这时连接被关闭,此时 errno 应该不 等于 EINTR,如果别的线程正好设置 errno 为 EINTR,这时程序就可能进入死循环
其它的错误码处理也可能进入不可预测的分支
在线程需求刚开始时,很多方面技术和标准(TLS)还不够成熟,所以在 为 了 解决这个重入问题引入了一个解决方案,把 errno 定义为一个宏: extern int *__errno_location (void); #define errno (*__errno_location()) 在上面的方案里,访问errno 之前先调用__errno_location()函数,线程库提供这个 函数,不同线程返回各自errno 的地址,从而解决这个重入问题
在编译时加 -D_REENTRANT 就是启用上面的宏,避免 errno 重入
另外 -D_REENTRANT 还影响一些 stdio 的函数
在较高版本的gcc 里,有很多嵌入函数的优化,比如把 printf(“Hello\n”); 优化为 puts(“hel