1.常用信号
SIGABRT: 调用abort函数产生此信号
SIGALRM: 调用alarm函数超时产生信号
SIGCHLD: 子进程终止将发送该信号给父进程
SIGINT: CTRL+C中断键
SIGSEGV: 无效内存引用(Segmentation Fault)
SIGUSR1: 用户自定义的信号,用于应用程序
2.信号处理
最简单的借口signal函数:
#include
void (signal(int signo,void (func)(int)))(int);
typedef void (sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
signal函数返回一个函数指针,该函数指针指向一个函数,该函数返回void,参数为int
signal函数有两个参数,第一个参数是int,第二个参数是一个函数指针,该函数指针指向返回void,带一个参数int的函数
加上typedef就清晰很多。
3.可重入函数
异步信号类似于硬件中断,主程序在执行时捕捉到信号,将进入信号处理函数中。
假设,当主程序正在malloc的时候,收到异步信号,在信号处理函数中继续调用malloc,结果是怎样的?
这种行为是不可预知的,因此malloc函数被称为不可重入的函数。
不可重入的函数有以下特性:
1.使用静态数据结构
2.调用malloc或者free
3.标准I/O函数
4.kill和raise函数
在终端调用kill命令可以向特定的进程发送信号。代码中可以使用raise和kill两个函数
#include
int kill(pid_t pid,int signo);
int raise(int signo);
raise表示向本进程发送异步信号,等价于kill(getpid(),signo)
static void sig_usr(int signo)
{
if(signo == SIGUSR1)
{
printf(“SIGUSR1 received\r\n”);
}
else if(signo == SIGUSR2)
{
printf(“SIGUSR2 received\r\n”);
}
else
{
printf(“received signal %d\r\n”,signo);
}
}
int main(int argc, char *argv)
{
if(signal(SIGUSR1,sig_usr)==SIG_ERR)
{
printf(“SIGUSR1 ERROR \r\n”);
return -1;
}
if(signal(SIGUSR2,sig_usr)==SIG_ERR)
{
printf(“SIGUSR2 ERROR \r\n”);
return -1;
}
kill(getpid(),SIGUSR1);
sleep(1);
raise(SIGUSR2);
sleep(1);
raise(SIGINT);//ctrl+c signal
sleep(10);//never execute
return 0;
}
5.alarm和pause函数
#include
unsigned int alarm(unsigned int seconds);
这两个函数在之前的代码中有所涉及:
alarm函数可以指定秒之后产生一个SIGALRM信号
pause函数可以休眠直到收到异步信号
用他俩组合可以写一个sleep函数
#include
#include
static void sig_alrm(int signo)
{}
unsigned int sleep1(unsigned int seconds)
{
if(signal(SIGALRM,sig_alrm)==SIG_ERR)
return (seconds);
alarm(seconds);
pause();
return (alarm(0));
}