一、更多信号发送函数
(1)alarm SIGALRM
(2)setitimer SIGALRM SIGVTALRM SIGPROF
(3)abort SIGABRT
间接递归 handler->SIGALRM->handler
kill -ALRM `ps aux | grep alarm | grep -v grep | awk '{ print $2}'`
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
void handler(int sig);
int main(int argc, char *argv[])
{
if (signal(SIGALRM, handler) == SIG_ERR)
ERR_EXIT("signal error");
alarm(1);
for (;;)
pause();
return 0;
}
void handler(int sig)
{
printf("recv a sig=%d\n", sig);
alarm(1);
}
二、可重入如函数
(1)为了增强程序的稳定性,在信号处理函数中应使用可重入函数。
(2)所谓可重入函数是指一个可以被多个任务调用的过程,任务在调用时不必担心数据是否会出错。因为进程在收到信号后,就将跳转到信号处理函数去接着执行。如果信号处理函数中使用了不可重入函数,那么信号处理函数可能会修改原来进程中不应该被修改的数据,这样进程从信号处理函数中返回接着执行时,可能会出现不可预料的后果。不可再入函数在信号处理函数中被视为不安全函数。
(3)满足下列条件的函数多数是不可再入的:(1)使用静态的数据结构,如getlogin(),gmtime(),getgrgid(),getgrnam(),getpwuid()以及getpwnam()或者全局变量等等;(2)函数实现时,调用了malloc()或者free()函数;(3)实现时使用了标准I/O函数的
(4)哪些函数可以signal信号处理函数中使用?man 7 signal
下边的例子:g_data的赋值不是原子性的。g_data是全局变量,出现SIGALRM信号时候,到handler函数中处理。在main中for循环g_data的赋值可能出现的情况:
g_data为0,0,在g_data = ones的时候,可能在g_data =1,0时出现SIGALRM
g_data为1,1,在g_data = zeros的时候,可能在g_data =0,1时出现SIGALRM
被中断之前的程序和可能跟中断处理程序共享数据
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
typedef struct
{
int a;
int b;
} TEST;
TEST g_data;
void handler(int sig);
int main(int argc, char *argv[])
{
TEST zeros = {0, 0};
TEST ones = {1, 1};
if (signal(SIGALRM, handler) == SIG_ERR)
ERR_EXIT("signal error");
g_data = zeros;
alarm(1);
for (;;)
{
g_data = zeros;
g_data = ones;
}
return 0;
}
void unsafe_fun()
{
printf("%d %d\n", g_data.a, g_data.b);
}
void handler(int sig)
{
unsafe_fun();
alarm(1);
}