c – 信号如何工作?

信号在unix中如何工作?我经历了史蒂文斯史蒂文斯,但是无法理解.请帮帮我.
下面的解释不完全是一样的,不同系统之间的差异在几个方面有所不同(甚至在某些部分甚至不同的硬件上也可能是相同的操作系统),但是我认为,一般来说,满足你的好奇心就足够了使用它们.大多数人开始使用编程中的信号,甚至没有这种程度的理解,但在我很舒服地使用它们之前,我想了解它们.

信号传递

操作系统内核有一个称为过程控制块的数据结构,每个进程都有运行的进程控制块,该进程具有关于该进程的数据.这可以通过进程id(PID)查找,并包括一个信号动作和未决信号表.

当信号发送到进程时,OS内核将查找该进程的进程控制块,并检查信号操作表以定位要发送的特定信号的操作.如果信号动作值为SIG_IGN,则内核将忘记新信号.如果信号动作值是SIG_DFL,那么内核会在另一个表中查找该信号的默认信号处理动作,并对该动作进行预处理.如果这些值是其他的,那么这个值被认为是发送到哪个应该被调用的信号的过程中的函数地址. SIG_IGN和SIG_DFL的值是转换为函数指针的数字,其值不是进程地址空间内的有效地址(例如0和1,它们都在第0页,从不映射到进程).

如果信号处理功能是通过进程注册的(信号动作值既不是SIG_IGN或SIG_DFL),则为该信号提供待处理信号表中的条目,并将该进程标记为准备运行(可能已经在等待一些东西,像数据可用于一个电话读取,等待一个信号,或其他几件事情).

现在下一次运行该过程时,OS内核将首先向堆栈添加一些数据,并更改该进程的指令指针,以使其看起来几乎像进程本身刚刚调用了信号处理程序.这不完全正确,实际上偏离了实际发生的情况,我会再多谈一谈.

信号处理函数可以做任何事情(它是代表它被调用的进程的一部分,所以它是用关于该程序应该对该信号做什么的知识)编写的.当信号处理程序返回时,该进程的常规代码将再次开始执行. (再次,不准确,但下一个更多)

好的,上面应该给你一个很好的想法如何传递信号到一个过程.我认为这个不错的主意版本是需要的,然后才能掌握整个想法,其中包括一些更复杂的东西.

操作系统内核通常需要知道信号处理程序何时返回.这是因为信号处理程序采用参数(可能需要堆栈空间),因此可以在信号处理程序执行期间阻止相同的信号传送两次,和/或在信号传递后重新启动系统调用.要完成这一点比堆栈和指令指针更改一点.

要发生的是,内核需要使进程告诉它已经完成了执行信号处理程序的功能.这可以通过将一部分RAM映射到进程的地址空间中,该空间包含用于使该系统调用的代码,并使信号处理函数的返回地址(当此函数开始运行时,堆栈上的最高值)为这段代码.我认为这是如何在Linux中完成的(至少是较新的版本).另一种完成此操作的方法(我不知道这是否完成,但可能会)会使信号处理函数的返回地址成为无效的地址(如NULL),这将导致大多数系统中的中断,这将使OS内核再次控制.这样做并不重要,但是内核必须再次获得控制来修复堆栈,并且知道信号处理程序已经完成.

在我想到的另一个问题我了解

Linux内核确实将页面映射到这个过程中,但是实际的系统调用注册信号处理程序(什么sigaction调用)需要一个参数sa_restore参数,这是一个应该用作信号返回地址的地址处理程序,内核只是确保它放在那里.这个地址上的代码发出了我完成的系统调用(sigreturn),内核知道信号处理程序已经完成了.

信号发生

我主要假设你知道信号是如何产生的.操作系统可以代表一个进程,由于某些事情发生,如定时器到期,子进程死亡,访问它不应访问的内存,或发出不应该的指令(或不存在的指令)或有特权的)或许多其他事情.定时器的功能与其他功能有些不同,因为它可能在进程没有运行时发生,更像是用kill系统调用发送的信号.对于代表当前进程发送的非定时器相关信号,当发生中断时会产生这些信号,因为当前进程出现错误.该中断给出内核控制(就像系统调用),内核生成要传递到当前进程的信号.

http://stackoverflow.com/questions/4208004/how-do-signals-work

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:c – 信号如何工作?