信号
什么是信号?
烽火戏诸侯的故事大家应该都知道,烽火就是信号
在Linux中,信号是一个软件中断,用来通知进程发生了某件事情,中断进程当前操作,让进程去处理这事件,当然前提是进程必须识别这些信号
信号生命周期:信号的产生 -> 在进程中注册(通知进程) -> 在进程中注销 -> 信号的处理
信号的种类:62种信号—两大类型:非可靠信号(1-31号)/可靠信号(34-64号)
相关命令:查看信号种类使用 kill -l
kill杀死进程的原理:向进程发送信号
信号的产生:
硬件产生:
- Ctrl+c(中断)
- ctrl+|(退出)
- ctrl+z(停止)
软件产生:
- kill -signum -p pid(向进程发送一个signum信号)
- int kill(int pid,int signum);
- int raise(int signum); 给进程自身发送sig信号
- void abort(void);给自己发送SIGABRT信号
- unsigned int alarm(unsigned int seconds);经过seconds秒之后给自己发送一个SIGALRM信号—定时器 sec==0,表示取消上一个未到的定时器
信号在进程中的注册:在进程PCB中做标记,标记进程收到了哪些信号
- 非可靠信号注册:判断PCB中的pending位图中相应信号是否已经注册;若未注册;则位图修改为1,向sigqueue链表中添加一个信号节点;若已经注册,则不作任何操作(事件丢失)
- 可靠信号注册:向链表中添加一个新的信号节点(事件不会丢失)
信号在进程中的注销:
- 非可靠信号:节点只有一个,注销就是删除节点,位图置0
- 可靠信号:节点可能有多个,注销就是删除一个节点,判断链表中是否还有相同信号的节点;若没有则位图置0;否则位图不变依然需要标记有这个信号待处理
信号的处理:
信号的处理并不是立即被处理,而是选择一个合适的时机去处理信号,进程的运行从内核态返回用户态的时候
进程如何从用户态切换到内核态:发起系统调用;程序异常;中断
进程运行的代码若是库函数或者用户自己写的函数,就说进程当前运行在用户态
信号处理的方式:
- 默认处理方式,既定义好的处理方式
- 忽略处理方式,处理动作中什么都不做
- 自定义处理方式,用户自己确定信号如何处理–自定义信号的处理函数替换原有的处理函数
如何修改信号处理方式:
sighandler_t signal(int signum,sighandler_t handler);
- signum:信号编号,替换的signum这个信号的处理函数
- handler:这是一个函数指针,是用户传入的处理函数(SIG_DFL:信号的默认处理动作,SIG_IGN:信号的忽略处理动作)
信号的阻塞:
信号的阻塞就是阻止信号被递达(递达就是实际执行信号的处理动作),信号依然可以被注册,只是暂时不处理。进程可以选择阻塞某个信号,这个信号将保持在未决状态,直到进程接触对这个信号的阻塞才执行递达的动作
注意:9号和19号信号无法被阻塞、自定义和忽略