-
目录
信号处理过程中的三张位图表:block,pending,handler
-
信号的基本结论
- 信号在OS中随时都可能产生!
- 进程要认识这个信号
- 进程知道信号产生了,该如何处理?
- 进程可能正在做着更重要的事情,把到来的信号暂不处理。
- 进程记得这个信号
- 进程在合适的时候会去处理这个信号
-
信号的概念
- Linux系统提供的一种,向指定进程发送特定事件的方式
- 信号产生是异步的
-
信号处理
- a.默认动作:终止自己,暂停,忽略...
- b.忽略动作
- c.自定义处理---信号的捕捉
- 对信号的自定义捕捉,我们只需要捕捉一次,后续一直有效
- signal:当进程收到sig信号时,会使用handler方法
- 忽略一个信号 :在signal的第二个参数传递一个宏:SIG_IGN,使用默认的:SIG_DFL
-
信号产生
-
信号的发送
- 修改指定进程pcb中的信号的指定位图,0->1,写信号
- 键盘可以产生信号
- 本质是OS更改pcb中的状态(位图)
-
系统调用
-
kill:
-
系统调用的kill
- kill -l :查询信号种类
-
-
模拟实现kill命令
-
raise函数:
-
作用:给当前进程发送sig号信号
-
abort函数:
- 作用:终止进程,向调用进程发送6号信号
-
不接受信号的自定义捕获的宏
-
-
-
软件条件
-
设置闹钟
-
alarm:
- seconds秒后OS发送14号信号
- OS要对闹钟进行管理:先描述在组织
- struct alarm{}
- 被大小堆管理
-
- IO很慢
- alarm(0)表示:取消闹钟,alarm的返回值是上一个闹钟的剩余时间
- 闹钟默认只触发一次!
-
-
异常
- 1.SIGFPE---8号信号
- 2.SIGSEGV---11号信号---段错误---越界
- 页表转换失败!
- 再谈cpu
- cpu是如何得知运算是正常的还是异常的?
-
Core && Term
- Core:让进程异常终止,但是会形成一个debug信息
- debug信息:形成一个core文件--->存储的是进程退出的时候的镜像数据----核心转储
- Term:让进程异常终止
- Core:让进程异常终止,但是会形成一个debug信息
-
-
_信号保存
- 进程可以选择阻塞某个信号
- 阻塞一个信号,那么对应的信号一旦产生,永不递达,直到主动解除阻塞!
-
信号集:sigset_t
-
操作函数
-
1.sigprocmask函数:
-
作用:修改进程内核的block表!
- 第一个参数
- SIG_BLOCK
- SIG_UNBLOCK
- SIG_SETMASK
- 第三个参数:给用户返回一张原有的位图表
- 解除屏蔽后,一般会立即处理当前被接触的信号(如果被pending)!!
- pending位图是在执行handler方法之前就被清零了!!
- 第一个参数
-
sigpending函数:
- 作用:获取当前进程的pending位图
- 清空输入的set位图
- 增加指定信号到set信号集中
- 判断一个信号在不在一个信号集中
-
-
三张信号表
- 阻塞表:block
- 递达表:pending
- 信号处理表:handler
-
- 进程可以选择阻塞某个信号
-
_信号处理
- 信号的捕捉:要经历4次状态的切换!在内核态切换回用户态的时候,会检测信号的状态
- _地址空间
- 不同进程之间共享一份内核级页表--->【3,4】GB
- _键盘输入数据的过程
- 按下键盘产生中断信号,通过某种硬件被cpu读取到,转而由cpu向OS中的中断向量表中(函数指针数组)中下标访问键盘方法!!
- 内核态-->用户态之间的切换
- 2者相互隔开的!用户态[0,3]GB,内核【3,4】GB,二者互不干扰(是由CPU保证的!)
- 程序运行从用户态切换到内核态的操作:中断/异常/系统调用
-
系统调用
-
对特定信号进行捕捉
- 可以查阅man手册-->sigaction-->struct sigation结构体
-
- 正在处理被捕捉的特定的信号时,该信号种类将会被OS屏蔽,直到本次特定的信号处理结束!
- 如果想要同时屏蔽多个信号,可以通过sigaddset设置进mask中
-
_重入函数
- _可重入函数
- _不可重入函数
- 大部分函数都不是可重入函数!
-
volatile关键字
- 编译器的优化级别: O0 O1 O2 O3
- 当开启优化等级时,CPU寄存器会隐藏内存中的真实值 (就不会每次都去内存中拿值)
- volatile关键字:修饰变量,让代码无视优化,保证内存的可见性 ---->volatile int a = 0;
- 编译器的优化级别: O0 O1 O2 O3
-
重谈进程等待
- 子进程退出的同时会发送SIGCHLD---17号信号
- 既然子进程退出会发送信号,那么以后就不用在main函数的父进程代码中去等待子进程了,可以通过signal捕捉信号,通过handler方法去等待子进程,waitpid(-1,nullptr,0);如果多个子进程同时退出,那么就需要通过循环去不断的等待对应的子进程。
- 通过 signal(SIGCHLD,SIG_IGN):自动回收子进程!
-
信号处理过程中的三张位图表:block,pending,handler
- _block
- 判断某个信号是否为阻塞状态,是为1,否为0,注意!如果信号被阻塞,仍然可以被添加进pending表中!!
- _pending
- pending集合代表的是该信号是否产生了,如果对应的比特位为1,代表着该信号已经产生,如果此时该信号未被阻塞,那么就会在合适的时候对该信号进行处理。(这个合适的时候就是当进程从内核态转化为用户态的时候)。 处理的方式就是对应handler表中的方式
- _handler
- handler集合代表着该信号的处理方式,处理方式有三种,如下:
- 忽略一个信号 :在signal的第二个参数传递一个宏:SIG_IGN,使用默认的:SIG_DFL
- _block