目录
1、信号的概念
又叫软中断,可以通过函数/按键产生。
2、如何查看
kill -l
man 7 signal
3、分类
1. 标准信号(1~31)
2. 实时信号(34~64)
4、标准信号的默认行为
TERM 接收到信号的进程终止
CORE 接受到信号的进程终止并产生dump文件
IGN 接受到信号的进程忽略
STOP 接受到信号的进程暂停
CONT 接受到信号的暂停的进程继续
5、特点
1. 丢失
2. 会打断阻塞的系统调用
3. 同一个信号不会嵌套相应---》执行信号处理函数期间mask置1了
4. 不能在信号处理函数中进程longjmp跳转
5. 如何忽略一个信号? mask置1
6、产生信号
1. 按键 Ctrl+c-->SIGINT Ctrl+\----SIGQUIT Ctrl+z--->SIGSTOP
2. alarm(2)/setitimer(2)---->SIGALRM
3. kill(2)
4. 程序段错误
7、注册信号行为
#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
signum:指定的信号,可以为除SIGKILL 及SIGSTOP外的任何信号
act: 信号处理方式
oldact: 旧的信号处理方式 将存储到此指针指向的结构体
结构体类型如下: 可参考Linux——信号处理函数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);
};
8、等待信号的到来
#include <unistd.h>
int pause(void);
9、信号集
sigset_t
sigemptyset(2) 空集
sigfullset(2) 满集
sigaddset(2) 将指定信号加入到集合
sigdelset(2) 将信号从集合中移除
#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum);
10、信号屏蔽字
#include <signal.h>
/* Prototype for the glibc wrapper function */
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
11、重入
第一次调用还没结束,就发生了第二次调用
信号处理函数极可能发生重入,两个信号注册了同一个信号处理函数
12、练习
1、使用sigaction函数注册信号,调用屏蔽函数屏蔽2、3号信号
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
/*
打印每一行*不受2和3信号干扰
*/
static void sig_handler(int s);
int main(void)
{
sigset_t set, oldset;
struct sigaction act, oldact;
// signal(SIGINT, sig_handler);
act.sa_handler = sig_handler;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(SIGINT, &act, &oldact);
// signal(SIGQUIT, sig_handler);
act.sa_handler = SIG_DFL;
sigaction(SIGQUIT, &act, NULL);
// 初始化集合
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigaddset(&set, SIGQUIT);
for (int i = 0; i < 5; i++) {
// 加入
sleep(1);
sigprocmask(SIG_BLOCK, &set, &oldset);
for (int j = 0; j < 5; j++) {
write(1, "*", 1);
sleep(1);
}
write(1, "\n", 1);
// 设置
sigprocmask(SIG_SETMASK, &oldset, NULL);
}
return 0;
}
static void sig_handler(int s)
{
write(1, "!", 1);
}