@[TOC](第九周学习笔记)
# 1. 信号的初步认识
## 1.1 信号的特点
信号所携带的信息量少,操作简单
## 1.2 信号的状态
1. 产生
①由键盘产生:例如Ctrl+c,Ctrl+
②命令:kill
③系统函数:kil
④软条件:定时器
⑤硬件:段错误,除0错误
> 由键盘和和硬件产生的信号统称为硬件方式,其余的为软件方式
2. 未决状态
处在该状态的信号没有被处理。
3. 递达状态
信号被处理。处理信号的方式如下:
- 忽略
- 捕捉
- 执行了默认动作
信号是由内核发送的,优先级比较高。进程收到信号后,会暂停正在处理的事情,优先处理信号,处理完成之后继续原来的工作
## 1.3 处理方式
1. 忽略信号,这是大多程序对信号的处理方式,但SIGKILL和SIGSTOP信号不能被忽略。这是为了最后能够有一种方式结束掉进程
2. 捕捉信号,捕捉信号后可以做相应的一些处理
3. 执行默认动作,大多数信号的默认动作为终止进程
## 1.4 查看信号
使用 kill -l 命令可以查看信号
# 2.信号集
## 2.1 信号集的相关概念
1. 未决信号集:没有被当前进程处理的信号
2. 阻塞信号集:将某个信号放到阻塞信号集,这个信号就不会被进程处理,阻塞解除之后,信号被处理。
信号产生后,处于未决状态,进程受到信号后信号会被放入未决信号集中。在未决信号集中的信号等待被处理,进程会判断阻塞信号集中信号对应的标志位是否为1,如果为1不处理该信号,如果为0处理该信号
3. 自定义信号集:用户可以使用自定义信号集对信号集进行操作。
相关处理函数如下:
- 将set集合置空
```c
int sigemptyset(sigset_t *set);
```
- 将所有信号加入set集合
```c
int sigfillset(sigset_t *set);
```
- 将signo信号加入到set集合
```c
int sigaddset(sigset_t, *set, int signo);
```
- 从信号集中移除signo信号
```c
int sigdelset(sigset_t *set, int signo);
```
- 判断信号是否存在
```c
int sigismember(const sigset_t *set, int signo);
```
- 检测信号集是否为空
```c
int sigisemptyset(const sigset_t *set);
```
- 按逻辑与方式将两个信号集并
```c
int sigandset(sigset_t *set, const sigset_t *left, const sigset_t *right);
```
*按逻辑或方式将两个信号集并
```c
int sigorset(sigset_t *set, const sigset_t *left, const sigset_t *right);
```
**sigprocmask函数**
- 屏蔽按到接触信号屏蔽,将自定义信号集设置给阻塞信号集
- 函数原型:
```c
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
```
# 3. 信号的捕捉
1. signal函数
```c
typedef void (*sighandler_t)(int);
sighandler_t signal(
int signum, //要捕捉的信号
sighandler_t handler //执行的动作
);
```
handler是一个函数指针,函数指向的类型为*sighandler_t,即它指向的函数有一个int型参数,返回类型为void
> 如果handler不是函数指针,就必须设置为SIG_IN(忽略该信号),SIG_DFL(执行默认动作)
2. sigaction函数:可以读取和修改与指定信号相关联的处理动作。
```c
int sigaction(
int signum, //捕捉的信号
construction struct sigaction *act, //信号的处理函数
struct sigaction *oldact //旧的信号处理函数被存储在这
);
/*sigaction结构体*/
struct sigaction {
void (*sa_handler)(int); //信号的处理方式
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask; //在信号处理函数执行过程中,临时屏蔽指定的信号,额外屏蔽
int sa_flags; //通常设置为0
void (*sa_restorer)(void); //不再使用
};
```
处理方式:
1. 若act为非空,则根据act结构体中的信号处理方式处理信号
2. 若oldatc为非空,则根据原来的信号处理函数处理信号,根据act中的设置处理动作
3. handler 的设置与上述signal的相同,如果handler不是函数指针,就必须设置为SIG_IN(忽略该信号),SIG_DFL(执行默认动作)
**内核实现信号的捕捉**
1. 用户注册一个信号处理函数sighandler。
2. 正在运行的程序,遇到中断、异常或是系统调用时进入内核态。
3. 内核在处理完异常返回主函数之前,会检查有无信号未处理。检查到有信号未处理,并按照用户自定义的函数处理,如果没有自定义函数,则按照默认动作处理。
4. 若设置了自定义处理函数,内核返回用户态执行sighandler函数
5. 执行完sighandler函数后,执行系统调用sigreturn回到内核态
6. 检查是否还有信号需要处理,如果没有就返回主程序继续主程序
# chatgpt问答
标签:set,sigset,处理,笔记,学习,int,信号,cint,第九 From: https://www.cnblogs.com/moynaliao/p/17826186.html