可重入:
lfl@ubuntu:/usr/include$ vi errno.h
重点看该文件中下面的内容
/* Declare the `errno' variable, unless it's defined as a macro by
bits/errno.h. This is the case in GNU, where it is a per-thread
variable. This redeclaration using the macro still works, but it
will be a function declaration without a prototype and may trigger
a -Wstrict-prototypes warning. */
#ifndef errno
extern int errno;
#endif
红色字体部分即说明errno是一个宏。
lfl@ubuntu:/usr/include/i386-linux-gnu/bits$ vi errno.h
重点看该文件的中下面的内容:
# ifndef __ASSEMBLER__
/* Function to get address of global `errno' variable. */
extern int *__errno_location (void) __THROW __attribute__ ((__const__));
# if !defined _LIBC || defined _LIBC_REENTRANT
/* When using threads, errno is a per-thread value. */
# define errno (*__errno_location ()) //errno 是个宏,代表的是个函数。
# endif
# endif /* !__ASSEMBLER__ */
#endif /* _ERRNO_H */
文件reentrant.c 的内容如下:
#include <errno.h>
int main()
{
errno;
return 0;
}
预处理的过程可以将宏进行替换,下面就进行预处理
lfl@ubuntu:~/test$ gcc -E reentrant.c -o reentrant.i
文件reentrant.i的内容如下:
# 2 "reentrant.c" 2
int main()
{
(*__errno_location ()); //宏errno被替换成这个函数了。
return 0;
}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
例子:
int global_val 2;//定义个全局变量
void func()
{
global_val++;
}
如果有N个进程调用该函数,而global_val是个全局变量,如果某个进程加上-D _REENTRANT,则可重入,即该进程的global_val不会受其他进程的影响;但是没加-D _REENTRANT的那N-1个进程调用该函数时变量global_val就会彼此影响,出现不可预料的结果。不会影响的原因是,加-D _REENTRANT的进程虽然调用的还是这个函数,但是不同的时该机制自动把该函数变成了
void func_r()
{
global_val++;
}
跟其他进程调用的函数不同了,那么自然就不会影响本进程了,即可以重去。