可重入函数(用于信号处理函数、 且 安全时的叫法),即是在信号处理函数中可以调用的函数,他们是安全的,不安全的如malloc(试想:线程正在调用malloc进行分配,而信号来了,在处理函数里面有调用malloc,那么就很有可能对进程造成破坏,破坏储存区维护的链表)、getpwnam等
可重入函数在处理操作期间,会阻塞任何会引起不一致的信号发送。
试想下面一个情况:
因为在信号处理函数执行时,如果里面执行了低俗系统调用 and 此信号处理函数没有屏蔽其它信号(如SIGUSR1),那么这时若果产生了SIGUSR1信号,那么由将产生中断,调用SIGUSR1的处理函数:
<pre name="code" class="cpp">#include <unistd.h> #include <signal.h> #include <stdio.h> void signal_1(int sig) { printf("Start signal_1...\n"); //sleep(20); malloc memory ... printf("End signal_1\n"); } void signal_2(int sig) { malloc memory ... printf("Process signal_2 ,OK\n"); } int main(int argc, char *argv[]) { sigset_t set_1; sigemptyset(&set_1); struct sigaction sa_1; sa_1.sa_handler = &signal_1; sa_1.sa_mask = set_1; sa_1.sa_flags = SA_RESTART; sigset_t set_2; sigemptyset(&set_2); struct sigaction sa_2; sa_2.sa_handler = &signal_2; sa_2.sa_mask = set_2; sa_2.sa_flags = SA_RESTART; sigaction(SIGUSR1, &sa_1, NULL); sigaction(SIGUSR2, &sa_2, NULL); printf("Start pause...(PID:%d)\n", getpid()); pause(); return 0; }
上面程序运行,先发送SIGUSR1 然后SIGUSR2,(不注释sleep忽略memory )输出:
$ ./sigproc Start pause...(PID:7089) Start signal_1... Process signal_2 ,OK End signal_1
那么我们可以知道,如果此时阻塞了SIGUSR2信号,那么signal_1不就安全了吗(忽略其它信号也有影响的情况先)
对的,如果使用sigaction调用了设定了阻塞SIGUSR2,那么就行了,可重入函数就是基于这种思想,看上面粗线那句话。
补充:
errno是线程安全的,也就是每个线程会访问局部的errno
在一个main函数中,如果线程函数里调用低俗系统调用,那么就有可能产生错误、中断,那么errno值会被改变,而main函数调用也出错时,那么errno值就会被改变,
所以,在作为一个通用规则,处理函数最好的写法是:
void sigproc(int sig) { int tmp = errno; //信号处理函数真正的操作开始... //处理函数任务完成 errno = tmp; }