【Linux系统】信号

目录

 

一.信号的概念

1.生活中的信号

2.什么是信号

二.信号的产生

1.前台进程与后台进程

2. 中断

3.操作系统中的信号

4.产生信号的四种方式

(1)键盘输入产生信号

(2)系统调用产生信号

 (3)硬件异常产生信号

(4)软件条件产生信号

总结

5.操作系统中的时间(补充)

6.core和term

三.信号的保存 

1.信号未决,递达,阻塞

2.内核中关于信号的三张表

3.修改,查询阻塞和未决信号集

(1)系统提供给用户的数据类型sigset_t

(2)系统调用

四.信号的处理

1.用户态和内核态

(1)用户级页表和内核级页表

(2)用户态和内核态的标志

2.处理信号

3.系统调用

4.细节

五.信号的其他补充问题

1.函数重入

2.关键字volatile

3. SIGCHLD信号

(1)基于信号回收子进程

(2)手动忽略SIGCHLD


 

一.信号的概念

1.生活中的信号

红绿灯就是一种信号,因为我们

  1. 知道它的特征,能识别
  2. 知道对应的灯亮,意味着什么,要做什么
  1. 我为什么认识这个信号?因为有人提前告诉过我,所以信号没有产生的时候,我们已经能知道怎么处理这个信号,信号到来,我也能立即识别出来
  2. 信号的到来,我们并不清楚具体什么时候,即信号到来相对于我正在做的工作,是异步产生的
  3. 信号产生了,我们不一定要立即处理它,而是在合适的时候处理,所以我要有一种能力将已经到来的信号暂时保存

2.什么是信号

信号是向目标进程发送通知消息的一种机制。

目标进程能识别信号,并且知道怎么处理

二.信号的产生

1.前台进程与后台进程

进程分为前台和后台(./xxx &),前台进程在命令行操作时只能有1个,后台进程可以有多个

前台和后台的本质区别是前台进程能够接受用户输入,后台进程不能接受用户输入,所以前台进程只能有1个。键盘输入ctrl + c,前台进程接收(通过接收信号的方式来间接接收)后终止。

当我们启动一个前台进程,shell无法接收指令,因为它被操作系统提到后台。终止前台进程后,操作系统将shell提到前台,可以接收指令。shell也是一个进程,但是不能被ctrl+c终止。

  1. ctrl + c  :终止前台进程
  2. jobs   :查看后台进程
  3. fg [number]   :将后台进程提到前台
  4. ctrl + z  :将前台进程暂停,前台进程如果被暂停,会立即被操作系统提到后台,shell提到前台,否则键盘会失效
  5. bg [number]  :将后台暂停的进程在后台启动(一定是后台暂停的进程,因为只有shell在前台运行才能接收你的指令)
  6. 终止一个后台进程:(1)fg [number] ,  ctrl+c  (2)kill -9 pid

2. 中断

操作系统怎么知道键盘有输入?

CPU和外设有针脚相连(间接相连),不同外设可以向特定针脚发送电信号。给每个针脚一个编号,叫做中断号。当某个外设数据就绪时时,向针脚发送高电平,CPU识别到某个针脚的高电平,就将中断号写到寄存器,操作系统就可以读取到这个编号。

计算机启动时,操作系统会将一个函数指针数组加载到内存,这个数组叫做中断向量表,内容是各种外设的读取方法,数组下标就是对应外设的中断号。外设向CPU发送中断号后,操作系统会立即停止手头的工作,从寄存器读取中断号,到中断向量表寻找读取方法,将数据从外设读取到内存。

操作系统怎么知道键盘有输入?

当用户按下键盘,键盘向CPU发送电信号,CPU写入中断号,通知操作系统,操作系统提取中断号,执行中断向量表中的键盘驱动读取方法,将数据从外设拷贝到指定的缓冲区中。

信号就是用软件来模拟中断的行为,中断是外设和操作系统之间的信息通知,信号是进程和进程之间的信息通知。

3.操作系统中的信号

 man 7 signal :查询信号

我们既可以使用信号编号,也可以使用信号名称,实际上这些名称就是一个个宏。

细节:

  1. 没有0号信号。因为进程的退出信息有退出信号和退出码,如果退出信号为0,表示进程不是因为信号而退出,是正常终止的,所以没有0号信号是为了标识进程未收到信号正常退出。
  2. 1~31号信号是普通信号,34~64是实时信号,我们只谈普通信号
  3. 每个进程都有函数指针数组,信号编号和数组下标强相关(信号从1开始,下标从0开始)

4.产生信号的四种方式

(1)键盘输入产生信号

例如键盘输入ctrl+c,键盘向CPU触发中断,CPU通知操作系统,操作系统读取中断号,从中断向量表中调用键盘的驱动读取方法。键盘的数据分为普通数据和控制数据,操作系统解析”ctrl+c“为控制数据,所以不会把数据写到缓冲区,而是转化为向前台进程发送2号信号。

类似地,键盘输入ctrl+z 转化为向前台进程发送19号信号,该信号的默认处理方法是暂停进程。

键盘输入ctrl+\ 转化为向前台进程发送3号信号,该信号的默认处理方法是终止进程。

(2)系统调用产生信号

 功能:向指定的进程发送指定的信号

 功能:向本进程发送指定的信号

//代码实例:实现kill指令对应的可执行程序
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <string>
using namespace std;

void Usage(const string& proc)
{
    cout << "\nUsage: " << proc << "signo processid" << endl; 
}
int main(int argc, char* argv[])
{
    if (argc != 3)
    {
        Usage(argv[0]);
        return 0;
    }

    int signo = stoi(argv[1] + 1);
    int processid = stoi(argv[2]);
    kill(processid, signo);
}

 (3)硬件异常产生信号

除0错误

CPU执行进程的代码,例如10/0,状态寄存器中的溢出标志位被置1,CPU通知操作系统自己出现异常,操作系统将硬件异常,转换为向导致该异常的进程发送8号信号SIGFPE(float point exception),该信号的默认处理方法是终止进程。

void handler(int signo)
{
    cout << "signo: " << signo << endl;
    sleep(1);
}
int main()
{
    signal(8, handler);
    int a = 5 / 0;
    
    return 0;
}

以上代码会陷入死循环:CPU执行进程代码引发异常,不再向后执行,通知操作系统,操作系统让CPU调度其它进程,同时向目标进程发送8号信号,但由于用户对8号信号自定义捕捉,进程没有退出,当它重新被CPU调度时,硬件上下文加载到CPU中,再次引发异常。

解引用空指针

空指针就是进程地址空间中的0号地址,是一个无效地址,页表中没有映射关系。当CPU访问0号地址,通过MMU(内存管理单元,一种硬件,集成在CPU中),查询页表从虚

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值