sleep与信号唤醒的问题

sleep与信号唤醒的问题

内核对信号的处理方式

内核处理一个进程收到的信号时机是在一个进程从内核态返回用户态时。

所以,当一个进程在内核态下运行时,软中断信号并不立即起作用,要等待将返回用户态时才处理。(具体何时到到返回用户态的时间,下文会陈述)。

信号的接收不是由用户进程来完成的,而是由内核代理。当一个进程P2向另一个进程P1发送信号后,内核接受到信号,并将其放在P1的信号队列当中。当P1再次陷入内核态时,会检查信号队列,并根据相应的信号调取相应的信号处理函数。

信号的机制

信号检测和响应时机

刚才我们说,当P1再次陷入内核时,会检查信号队列。那么,P1什么时候会再次陷入内核呢?陷入内核后在什么时机会检测信号队列呢?

  1. 当前进程由于系统调用、中断或异常而进入系统空间以后,从系统空间返回到用户空间的前夕。
  2. 当前进程在内核中进入睡眠以后刚被唤醒的时候(必定是在系统调用中),或者由于不可忽略信号的存在而提前返回到用户空间。

进入信号处理函数

发现信号后,根据信号向量,知道了处理函数,那么该如何进入信号处理程序,又该如何返回呢?

我们知道,用户进程提供的信号处理函数是在用户态里的,而我们发现信号,找到信号处理函数的时刻处于内核态中,所以我们需要从内核态跑到用户态去执行信号处理程序,执行完毕后还要返回内核态。这个过程如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1GsJXnDG-1595514413521)(C:\Users\wwww\Desktop\20200425C语言笔记及代码\Linux课程\day08\信号处理函数的执行过程.png)]

sleep函数

sleep是一个系统调用,当调用该函数时就会进入到系统空间进行睡眠,如果在此时收到了比高优先级的中断(例如一些信号),那么就会从系统空间中返回用户空间去执行信号处理函数,因为信号处理函数是在用户空间上。

信号与sleep函数

如果要捕捉的信号发生于进程正在一个系统调用中时,并且该进程睡眠在可中断的优先级上,这时该信号引起进程作一次longjmp,跳出睡眠状态,返回用户态并执行信号处理例程。当从信号处理例程返回时,进程就象从系统调用返回一样,但返回了一个错误代码,指出该次系统调用曾经被中断。这要注意的是,BSD系统中内核可以自动地重新开始系统调用。

在介绍信号的时候,我们看到多个地方要求进程在检查收到信号后,从原来的系统调用中直接返回,而不是等到该调用完成。这种进程突然改变其上下文的情况,就是使用setjmp和longjmp的结果。setjmp将保存的上下文存入用户区,并继续在旧的上下文中执行。这就是说,进程执行一个系统调用,当因为资源或其他原因要去睡眠时,内核为进程作了一次setjmp,如果在睡眠中被信号唤醒,进程不能再进入睡眠时,内核为进程调用longjmp,该操作是内核为进程将原先setjmp调用保存在进程用户区的上下文恢复成现在的上下文,这样就使得进程可以恢复等待资源前的状态,而且内核为setjmp返回1,使得进程知道(注:知道是从longjmp调用的)。这就是它们的作用。

返回1,使得进程知道(注:知道是从longjmp调用的)。这就是它们的作用。

参考链接:https://www.cnblogs.com/charlesblc/p/6277848.html

猜你喜欢

转载自blog.csdn.net/qq_41775886/article/details/107549613
今日推荐