可重入函数(用于信号处理函数、 且 安全时的叫法),即是在信号处理函数中可以调用的函数,他们是安全的,不安全的如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
如果是使用了memory调用,好明显这两个信号处理函数也是不可重入的;
那么我们可以知道,如果此时阻塞了SIGUSR2信号,那么signal_1不就安全了吗(忽略其它信号也有影响的情况先)
对的,如果使用sigaction调用了设定了阻塞SIGUSR2,那么就行了,可重入函数就是基于这种思想,看上面粗线那句话。
补充:
errno是线程安全的,也就是每个线程会访问局部的errno
在一个main函数中,如果线程函数里调用低俗系统调用,那么就有可能产生错误、中断,那么errno值会被改变,而main函数调用也出错时,那么errno值就会被改变,
所以,在作为一个通用规则,处理函数最好的写法是:
void sigproc(int sig)
{
int tmp = errno;
//信号处理函数真正的操作开始...
//处理函数任务完成
errno = tmp;
}