猿问

errno是线程安全的吗?

在中errno.h,此变量被声明为extern int errno;是我的问题,errno在某些调用之后检查值还是在多线程代码中使用perror()是安全的。这是线程安全变量吗?如果没有,那还有什么选择呢?


我在x86体系结构上将Linux与gcc一起使用。



慕仙森
浏览 832回答 3
3回答

开心每一天1111

是Errno不再是一个简单的变量,它是幕后复杂的事情,特别是它具有线程安全性。见$ man 3 errno:ERRNO(3)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Linux Programmer’s Manual&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ERRNO(3)NAME&nbsp; &nbsp; &nbsp; &nbsp;errno - number of last errorSYNOPSIS&nbsp; &nbsp; &nbsp; &nbsp;#include <errno.h>DESCRIPTION&nbsp; &nbsp; &nbsp; ...&nbsp; &nbsp; &nbsp; &nbsp;errno is defined by the ISO C standard to be&nbsp; a&nbsp; modifiable&nbsp; lvalue&nbsp; of&nbsp; &nbsp; &nbsp; &nbsp;type&nbsp; int,&nbsp; and&nbsp; must not be explicitly declared; errno may be a macro.&nbsp; &nbsp; &nbsp; &nbsp;errno is thread-local; setting it in one thread&nbsp; does&nbsp; not&nbsp; affect&nbsp; its&nbsp; &nbsp; &nbsp; &nbsp;value in any other thread.我们可以仔细检查:$ cat > test.c#include <errno.h>f() { g(errno); }$ cc -E test.c | grep ^ff() { g((*__errno_location ())); }$&nbsp;

慕慕森

在errno.h中,此变量声明为extern int errno;这是C标准所说的:宏errno不必是对象的标识符。它可能会扩展为由函数调用(例如*errno())产生的可修改的左值。通常,errno是一个宏,它调用一个函数,该函数返回当前线程的错误号的地址,然后将其取消引用。这是我在Linux上的/usr/include/bits/errno.h:/* Function to get address of global `errno' variable.&nbsp; */extern int *__errno_location (void) __THROW __attribute__ ((__const__));#&nbsp; if !defined _LIBC || defined _LIBC_REENTRANT/* When using threads, errno is a per-thread value.&nbsp; */#&nbsp; &nbsp;define errno (*__errno_location ())#&nbsp; endif最后,它将生成这种代码:> cat essai.c#include <errno.h>intmain(void){&nbsp; &nbsp; errno = 0;&nbsp; &nbsp; return 0;}> gcc -c -Wall -Wextra -pedantic essai.c> objdump -d -M intel essai.oessai.o:&nbsp; &nbsp; &nbsp;file format elf32-i386Disassembly of section .text:00000000 <main>:&nbsp; &nbsp;0: 55&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push&nbsp; &nbsp;ebp&nbsp; &nbsp;1: 89 e5&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov&nbsp; &nbsp; ebp,esp&nbsp; &nbsp;3: 83 e4 f0&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; and&nbsp; &nbsp; esp,0xfffffff0&nbsp; &nbsp;6: e8 fc ff ff ff&nbsp; &nbsp; &nbsp; &nbsp; call&nbsp; &nbsp;7 <main+0x7>&nbsp; ; get address of errno in EAX&nbsp; &nbsp;b: c7 00 00 00 00 00&nbsp; &nbsp; &nbsp;mov&nbsp; &nbsp; DWORD PTR [eax],0x0&nbsp; ; store 0 in errno&nbsp; 11: b8 00 00 00 00&nbsp; &nbsp; &nbsp; &nbsp; mov&nbsp; &nbsp; eax,0x0&nbsp; 16: 89 ec&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov&nbsp; &nbsp; esp,ebp&nbsp; 18: 5d&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pop&nbsp; &nbsp; ebp&nbsp; 19: c3&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret
随时随地看视频慕课网APP
我要回答