Linux信号产生
目录
1.温故知新
2.Linux信号
1.温故知新
上一篇博客我们知道了我们进程结束,内存泄漏会被释放掉,还知道我们共享内存的访问速度快,它被创建出来和普通访问一样,不需要系统调用,导致速度快,共享内存生命周期随内核。
还知道系统调用也是有成本的。ipcs -m 查看共享内存 ipcs -p 查看消息队列。进程间通信总的有匿名管道,命名管道,共享内存,消息队列。它们的原理都是让不同的进程看到同一份资源,宏观上来为什么我们不同看到进程一份资源还是比较困难的,因为我们进程要保证它的独立性。我们还早知道了我们的并发编程的一些概念,共享资源是多个执行流都能看到的一份公共资源,被保护起来的共享资源叫临界资源,保护临界资源的代码叫临界区,任何时刻我们只允许一个执行流访问临界资源的时候叫互斥,在互斥的基础上给访问临界资源加以顺序就叫同步,我们保护临界资源是靠我们代码实现保护的,所谓的对共享资源的保护就是对我们临界区代码的保护。常见的保护方式就是互斥和同步。后来我们介绍了我们的信号量,它也是对我们临界区做保护的一种手段。它是通过让所有进程看到他,并且申请P,V操作来实现的,它保护共享资源,它自己本身也是共享的,因为多个进程都能看到它,所以它的操作都是原子的,这样就被保护起来了。
我们内核是怎么维护我们的IPC呢?我们在内核中创建一个数组,每个IPC结构体的第一个元素是我们的q_perm,q_perm也是一个结构体里面有属性,然后我们因为每个资源的结构体第一个元素都是相同的,在普通结构体中,我们知道第一个元素的地址,本质是字节的地址,我们通过强转可以访问整个结构体,我们内核为我们维护了一个数组,它们每一个元素指向我们的IPC的第一个元素,我们IPC的第一个元素相同,我们通过不同的数组下标访问不同的IPC,这种设计思想和我们的多态不谋而合,大量的工程实践发现我们同一个接口不同的效果是非常常用的,我们就把多态设计成语言的特性了,多态就是让我们不同对象调同一个接口可以产生不同的效果,这个就是我们IPC是同一个接口,不同的对象指向让我们得以产生不同的效果!
2.Linux信号
我们知道我们的信号有信号产生,信号保存,信号处理,我们从信号产生介绍起,我们信号的产生方式有键盘产生,kill命令产生,还有就是系统调用。但是为了防止恶意操作,有些信号是不可以被捕捉不可以被忽略的,比如我们的9号信号,如果我们一个进程故意忽略所有信号,那么我们不是就无法杀死这个进程了?为了防止这种情况的出现我们会设计出这个。
下面我们说可以通过系统调用产生信号,是怎么产生的呢?这是因为有Kill系统调用,raise,abort系统调用可以帮助我们产生信号。我们可以通过这个函数自己实现一个kill
我们还可以通过软件条件产生信号,比如坏掉的管道,会发信号给OS让进程自己崩掉。
还有一个系统调用alarm(seconds),这个是闹钟,就是我们设定一个秒数,到了之后就会自动向系统发送14号信号。
知道了闹钟的设定,那 我们怎么取消我们的闹钟呢?
首先我们只要再次alarm,它就会取消上一次闹钟的闹钟,如果我们alarm(0)就会取消我们的闹钟,它是怎么做到的呢?
我们会用最小堆来管理我们的闹钟,最近要响的闹钟会在堆顶。我们多个闹钟,我们需要对闹钟进行管理.
ps:这里有一个问题:我一个进程只有一个闹钟, 那我还管理什么,答案是我们一个OS内同时有多个进程,我们一个进程设定一个闹钟,但是我有许许多多的进程啊,这样我就要判断谁快要超时了,做出管理呀!
最后一种产生异常的方式:异常,我们的进程中出现了野指针或者我们的除0错误会自动崩溃,这是因为出现异常,让我们的进程崩掉了
当我们进行计算的时候,我们会将我们的数据写到CPU的寄存器,我们会有对应的寄存器来有溢出标志位,当它为1的时候我们本次运算就在硬件上报错了,我们操作系统要不要知道这次硬件报错?当然要知道,操作系统是软件和硬件的管理者,然后我们CPU在执行的时候一定是在调度某一个进程,我们当然知道目前的进程是谁了,当我们调度一个进程的时候,我们的CPU寄存器里面是我们当前进程的硬件上下文,当我们发生硬件报错之后,操作系统一般会杀掉这个进程,进程崩掉,我们的硬件上下文就要被释放CPU的报错就没有了,杀掉进程就不存在我们的报错了。
如果我们的进程没有退出,它计算不出答案我们操作系统会一直调度这个进程。