Bootstrap

Linux进程信号保存/操作系统运行原理

知识补充:

系统调用:pause(); 该函数可以等待发出信号

signal:可以进行信号捕捉

其中,信号捕捉分为三点:

1,默认

2,忽略

3,自定义

默认和忽略系统中给我们提供了具体调用方法:

默认:SIG_DFL

自定义:SIG_IGN

信号相关的其他概念

1,实际执行信号的处理动作称为信号递达

2,信号从产生到递达之间的状态叫做信号未决

3,进程可以选择阻塞某个信号

(信号产生之后会对阻塞的目标信号进行pending,永远不递达,除非我们解除阻塞)

4,被阻塞的信号产生时会一直处于未决状态,直到解除阻塞状态,信号才能执行递达的动作。

5,注意,忽略和阻塞是不同的,只要信号被阻塞就不会被递达,而忽略是递达之后可选的一种处理动作。

进程如何完成进程保存的

在task_struct中维护着三张表,分别叫block,pending,handler

pending

pending表本质就是位图(1-31)

含义:

1,比特位位置代表信号编号。

2,比特位内容 0/1 代表是否收到对应的信号。

pending位图就是当前进程收到的信号列表

handler

handler表本质其实是一个函数指针列表,信号编号-1就是函数指针数组的下标

所以,signal(2,handler)中2就是去找下标,handler就是去修改数组内的内容

这也就是为什么signal改一次之后,后面的内容都会变成自定义内容。

block

block表其实本质也是一张位图,也是维护1-31的内容

含义:

1,比特位位置代表信号编号

2,比特位内容0/1代表是否阻塞,屏蔽特定信号,决定了pending是否可以访问handler表。

我们可以提前屏蔽,屏蔽课收到信号两者毫无关系。

所以,要看某个信号是否要被处理,我们可以横着看:

如果block里值为1,pending值为1,就不递达

如果block里值为零,pending值为0,也不做处理

如果block里值为0,pending值为1,就会对信号进行处理:

信号集操作函数

sigset_t

这是系统封装的pending/block的数据类型,可对其内容进行改变,但是修改内容涉及位图的操作,容易产生失误,所以系统也提供了余其他函数来对sigset_t进行操作:

sigemptyset:可以将位图初始化为全0

sigfillset:可以将位初始化为全1

sigaddset:可以将signum信号添加到set中

sigdelset:可以将特定信号删除

sigismember:可以判断signum信号是否在set里

sigprocmask

该函数可以读或者该进程信号的屏蔽字:

其中,how代表用什么方式进行修改,系统提供了三种函数来供我们使用:

其中第三个参数是可以拷贝一份老的数据出来做备份的。

sigpending

sigpending的参数属于输出型参数,可以获取pending信号集

代码演示

接下来将用代码的方式来混用上面的函数,以便大家理解:

1,对2号信号进行屏蔽

2,如何获取pending表

3,如何解除屏蔽?

可以使用之前备份的oblock来进行备份:

代码如下:

可以看到,当我们解除了二号信号屏蔽,系统就会执行二号信号,二号信号默认行为是退出,如何我们没对信号进行捕捉,所以进程就会退出。

信号捕捉

在主函数因为中断,异常或系统调用将进入内核处理,处理完后可以递送的信号,字给到信号处理,如果信号处理为忽略或者默认就回到主流程,如果是自定义就会调用用户自定义函数,如何在进到内核流程中被中断的地方继续执行。

os运行状态

1,用户态---我自己写的代码

2,内核态---执行os代码

所以信号捕捉流程:

os是怎么运行的

1,硬件中断

在图中左侧有各种各样的外设,当他们的内容准备就绪时,就会通知中断控制器,通知cpu,cpu知道中断之后会回来获取中断号,如何去os根据中断号在中断向量表中找对应的方法并执行,当执行完毕之后会恢复现场并持续刚刚的工作。

2,时钟中断

此中断会一直推进os的调度,在当代设备中,有一个时钟源会一直给os发送时钟中断,而这个时钟源现在在cpu中,如果在外设的话就太慢了,而时钟源发送的频率称为主频,主频越高代表cpu利用效率越高,调用os的次数就越多,cpu也越贵。

此时我们知道,os是基于中断向量表工作的,cpu中时钟源会不断地推进os的运行

os这样就可以之间躺平,要什么就去向量表拿。

3,软件中断

除了上面说的硬件中断,还有软件中断,cpu用和汇编可以让cpu内部促发中断逻辑

4,什么是时间片?

就是时钟中断时固定的发过来:1纳秒

task_struct

{

int count = 1000;

count--;

if(count == 0);---

}

时间片本质就是一个计数器,当count==0时,就进行进程切换。

内核页表

一个进程中除了有用户页表,也有一个内核页表:

在每一个进程中,用户页表每个进程互不影响,相互独立,但是在所有进程中,内核页表整个系统就只有一个,所以无论进程怎么调用调度,都能找到同一个os。

;