信号处理函数的注册
入门版: signal
高级版:sigaction
信号处理函数
信号发送函数也不止一个,同样分为入门版(无法携带消息)和高级版(可以携带消息)
入门版:kill
高级版:sigqueue
一、入门版的收发信号 (signal收信号, kill发信号)
接下来利用signal 实现一下信号处理函数捕获信号 (收信号)
#include <signal.h>
#include <stdio.h>
// typedef void (*sighandler_t)(int);
// sighandler_t signal(int signum, sighandler_t handler);
void handler(int signum)
{
printf("get signum = %d\n",signum);
switch(signum){
case 2:
printf("SIGINT\n"); // ctrl + c
break;
case 9:
printf("SIGKILL"); // 企图捕获其它进程发过来的kill 信号
break;
case 10:
printf("SIGUSR1");
break;
}
printf("never quit\n");
}
int main()
{
signal(SIGINT, handler);
signal(SIGKILL, handler);
signal(SIGUSR1, handler);
while(1);
return 0;
}
按下ctrl + c

接下来看能不能捕获到 kill 信号 (发信号)

并不能捕捉到 kill 信号
自己实现一个kill函数,用于发信号
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
// int kill(pid_t pid, int sig);
int main(int argc, char **argv)
{
int signum;
int pid;
signum = atoi(argv[1]);
pid = atoi(argv[2]);
kill(pid, signum);
printf("send signal ok\n");
printf("signum = %d, pid = %d\n",signum, pid);
return 0;
}
用法

或者利用system 函数也可以实现这个功能(发信号)
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
// int kill(pid_t pid, int sig);
int main(int argc, char **argv)
{
int signum;
int pid;
char cmd[128] = {0};
signum = atoi(argv[1]);
pid = atoi(argv[2]);
printf("signum = %d, pid = %d\n",signum, pid);
sprintf(cmd, "kill -%d %d",signum, pid);
// kill(pid, signum);
system(cmd);
printf("send signal ok\n");
return 0;
}
二、高级版的收发信号
收信号:sigaction
原型:
#include <signal.h>
int sigaction(
int signum, // 第一个参数
const struct sigaction *act, // 第二个参数
struct sigaction *oldact // 第三个参数
);
第一个参数: int signum
第一个参数:signum:信号编号
第二个参数 const struct sigaction *act
第二个参数:sigaction 如下
struct sigaction {
void (*sa_handler)(int); // 第一个参数
void (*sa_sigaction)(int, siginfo_t *, void *); // 第二个参数
sigset_t sa_mask; // 第三个参数
int sa_flags; // 第四个参数
void (*sa_restorer)(void);
};
拆分结构体参数:
第一个参数:
void (*sa_handler)(int):信号处理函数,不接收数据
第二个参数 (编程的时候需要配置)
void (*sa_sigaction)(int, siginfo_t *, void *): 可以接收额外数据
1. int: 信号编号
2. siginfo_t *:结构体
拆分:
siginfo_t {
pid_t si_pid; // 谁发的
int si_int; // 整型数存放的地方
sigval_t si_value; // 信号的值
}
si_value:
union sigval {
int sival_int;
void *sival_ptr;
}
3. void *: 空:没有数据; 非空:有数据
第三个参数
sigset_t sa_mask:阻塞作用(默认就是阻塞)
第四个参数 (编程的时候需要配置)
int sa_flags:需要配置一个宏(SA_SIGINFO)
第三个参数: sigaction
sigaction 用来做备份(备份原操作)
发信号:sigqueue
原型:
#include <signal.h>
int sigqueue(
pid_t pid, // 第一个参数
int sig, // 第二个参数
const union sigval value // 第三个参数(联合体)
);
第一个参数
pid_t pid : 发给谁
第二个参数
int sig: 发的是什么信号
第三个参数
const union sigval value : 需要的消息
union sigval {
int sival_int;
void *sival_ptr;
}
携带消息实战代码:
收消息:(sigaction)
#include <signal.h>
#include <stdio.h>
// int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
void handler(int signum, siginfo_t *info, void *context)
{
printf("get signum %d\n",signum);
if(context != NULL){
printf("get data =%d\n",info->si_int);
printf("get data =%d\n",info->si_value.sival_int);
printf("from:%d\n",info->si_pid);
}
}
int main()
{
struct sigaction act;
printf("pid = %d\n",getpid());
act.sa_sigaction = handler;
act.sa_flags = SA_SIGINFO; // be able to get message
sigaction(SIGUSR1, &act, NULL);
while(1);
return 0;
}
发消息:(sigqueue)
#include <signal.h>
#include <stdio.h>
//int sigqueue(pid_t pid, int sig, const union sigval value);
int main(int argc, char **argv)
{
int signum;
int pid;
signum = atoi(argv[1]);
pid = atoi(argv[2]);
union sigval value;
value.sival_int = 100;
sigqueue(pid, signum, value);
printf("%d, done\n",getpid());
return 0;
}
结果
