简体   繁体   English

如果#define替换errno符号,如何初始化线程安全errno?

[英]How is thread-safe errno initialized if #define substitutes errno symbol?

I'm trying to understand how glibc initializes errno without the preprocessor substituting the errno symbol. 我试图理解glibc如何在没有预处理器替换errno符号的情况下初始化errno

I first tried to implement a simple version myself based on csu/errno-loc.c and csu/errno.c : 我首先尝试基于csu / errno-loc.ccsu / errno.c实现一个简单的版本:

myerrno.h myerrno.h

#ifndef MYERRNO_H
#define MYERRNO_H

extern int *myerrno_location(void);
#define myerrno (*myerrno_location())

#endif

myerrno.c myerrno.c

#include "myerrno.h"

static int myerrno = 0;

int *myerrno_location(void){
    return &myerrno;
}

However, when I try to compile I receive the following error messages: 但是,当我尝试编译时,我收到以下错误消息:

myerrno.c:3:1: error: function ‘myerrno_location’ is initialized like a variable
myerrno.c:3:12: error: static declaration of ‘myerrno_location’ follows non-static declaration
myerrno.h:4:13: note: previous declaration of ‘myerrno_location’ was here

I can tell that the preprocessor is substituting (*myerrno_location(void)) when it encounters myerrno on line 3 -- and naturally this is expected behavior. 我可以告诉预处理器在第3行遇到myerrno时替换(*myerrno_location(void)) - 自然这是预期的行为。

I don't understand why this isn't a problem for glibc . 我不明白为什么这对glibc来说不是问题。 How do thread-safe implementations of errno get around this preprocessor substitution issue without renaming the static errno variable? errno线程安全实现如何解决这个预处理器替换问题而不重命名静态errno变量?

Fixing your issue is as easy as changing the name of your static variable. 修复问题就像更改静态变量的名称一样简单。

static int myerrno_variable = 0;

int *myerrno_location(void){
    return &myerrno_variable;
}

Notice that your version is still not thread safe since all threads are accessing the same myerrno_variable . 请注意,由于所有线程都访问相同的myerrno_variable ,因此您的版本仍然不是线程安全的。 A real implementation would return a thread specific memory location. 真正的实现将返回特定于线程的内存位置。 In GCC, there is an extension that provides the __thread storage class. 在GCC中,有一个提供__thread存储类的扩展。 C.11 provides its own version of that called thread_local , but it is only available if thread support is provided by the implementation (which can be checked by looking if __STDC_NO_THREADS__ is defined or not). C.11提供了自己的那个名为thread_local的版本,但只有在实现提供了线程支持时才可用(可以通过查看是否定义了__STDC_NO_THREADS__来检查)。

static __thread int myerrno_variable_gcc;      /* if using GCC */
static thread_local int my_errno_variable_c11; /* if __STD_NO_THREADS__ isn't defined */

On a POSIX system without a thread local feature, an implementation could use pthread_getspecific() to get a pointer to thread specific data that was allocated for each thread, and set with pthread_setspecific() . 在没有线程局部特性的POSIX系统上,实现可以使用pthread_getspecific()来获取指向为每个线程分配的线程特定数据的指针,并使用pthread_setspecific()设置。 See the manual for more information. 有关详细信息,请参阅手册

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

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