20.Linux进程信号(一)
信号: 产生->保存->处理
一、预备知识
信号vs信号量->没有任何关系
什么叫做信号?
中断我们正在做的事情,是一种事件的异步通知机制。
同步和异步理解:
同步指事件发生具有一定的顺序性(如命名管道中服务端读方式打开会阻塞,直到客户端的写入打开),异步指事情发生没有顺序性(如共享内存的读取和写入没有顺序性)。
信号的产生相对于进程的运行是异步的。
信号是发送给进程的。
基本结论:
1.信号处理,进程在信号没有产生的时候,早就知道信号该如何处理了。
2.信号的处理,不是立即处理,而是可以等一会在处理,合适的时候,进行信号的处理。
3.人能识别信号,是被“提前教育”过的,进程也是如此,OS程序员设计的进程,进程早已内置对于信号的识别和处理方式。
4.信号源非常多->给进程产生信号的,信号源,也非常多。
SIGINT:键盘产生信号。
收到信号,处理信号(进程收到信号,合适的时候处理信号):
1.默认处理动作
2.自定义信号处理动作
3.忽略处理
自定义捕捉系统调用:
sighandler_t 实质上等同于void(*)(int)
sighandler_t signal(int signum, sighandler_t handler);
参数:
signum:信号编号
handler: 自定义的信号处理方式,当收到对应的信号,就回调执行handler方法。
返回值:成功返回handler,失败返回SIG_ERR(一个宏,通常定义为 (void (*)(int))-1,表示一个无效的函数指针),错误码被设置。
二、信号的产生
1.键盘产生信号
ctrl+C向前台进程发送2号信号。
相当一部分信号的处理动作就是让自己终止。
前台进程和后台进程:
./xxx 前台进程 ->键盘产生的信号,只能发送给前台进程。
./xxx & 后台进程
前台进程只能有一个,本质上前台进程就是要从标准输入获取数据的。
后台进程可以有多个。
前后台移动命令:
jobs-l 查看当前终端会话中通过
&
或Ctrl+Z
挂起的后台任务
fg 任务号 特定的进程,提到前台
ctrl+z 进程切换到后台,并且暂停bg 任务号 让指定的后台进程进行回复运行
什么叫做给进程发送信号?
信号产生之后,不是立即处理的,所以要求进程把信号记录下来。
发送信号本质:向目标进程写信号,修改位图!
信号记录在task_struct中,是一个位图结构->属于操作系统的数据结构对象->修改位图本质就是修改内核的数据->不管信号怎么产生,发送信号,在底层,必须让OS发送。
特别注意:不是所有信号都能被自定义捕捉。
2.系统调用产生信号
int kill(pid_t pid, int sig); //给目标进程发送信号
raise给自己发送信号,abort给自己进程发送终止信号(发送6号新号,要求进程必须处理,默认终止)。
3.系统指令kill产生信号
4.产生信号的方式(硬件异常)
常见的硬件异常:
除0,野指针。
信号全部都是操作系统发送的!
操作系统怎么知道犯错了?->操作系统是软硬件资源的管理者->CPU,寄存器,状态寄存器(标志寄存器:EFLAGS)可以判断溢出
野指针异常->cpu里的MMU将虚拟地址转化成物理地址失败了->硬件报错
5.产生信号的方式---软件条件
进程--管道--进程,在匿名管道,如果读端关闭,写端继续,操作系统就会发送SIGPIPE信号来终止写端进程,OS不做没有意义的事情。
调用alarm函数可以设定⼀个闹钟,也就是告诉内核在 seconds 秒之后给当前进程发SIGALRM 信号,该信号的默认处理动作是终止当前进程。这个函数的返回值是0或者是以前设定的闹钟时间还余下的秒数。例如:alarm(5)->过5秒终止,返回值是0alarm(5)->过3秒,设alarm(10)->过10秒终止了,返回值为2,即以前设定闹钟剩余的秒数pause函数作用:暂停,等待信号到来,直到信号处理动作结束,pause函数才会返回。操作系统本质:死循环pause,等待信号到来,每隔一段时间,CPU向操作系统发送硬件中断。如何理解闹钟:时间片本质就是一个计数器。闹钟理解:闹钟的结构里存有过期时间,组织方式可以理解成最小堆,将当前操作系统记录的时间戳与闹钟堆顶的时间戳进行比较,如果堆顶的时间戳大于等于操作系统当前记录的,就向对应的进程发送SIGALRM信号,同时把堆顶删除。