信号如何中断系统调用
Posted
技术标签:
【中文标题】信号如何中断系统调用【英文标题】:how can signals interrupt a system call 【发布时间】:2016-06-11 17:43:15 【问题描述】:我正在阅读一篇文章,我阅读了以下内容:假设我们要执行一个外部命令并等待它退出。我们不想永远等待,我们想设置一些超时时间,然后我们将杀死子进程。这该怎么做?要运行命令,我们使用 fork(2) 和 execve(2)。要等待特定进程退出,我们可以使用 waitpid(2) 函数,但它没有超时参数。我们还可以创建一个循环,在其中调用 sleep(3) 并将超时作为参数,并使用 sleep(3) 将被 SIGCHLD 信号中断的事实。该解决方案将起作用……几乎。它将包含一个竞争条件:如果进程立即退出,在我们调用 sleep(3) 之前,我们将等到超时到期。这是一场类似于前面描述的比赛。系统调用是如何中断的?子进程是向父进程还是系统调用 sleep(3) 发送信号?我不明白系统调用如何停止执行并传递给父进程,系统调用是否像另一个进程?
【问题讨论】:
【参考方案1】:系统调用是如何中断的?子进程是向父进程发送信号还是系统调用 sleep(3)?
当子进程执行系统调用exit(2)时,内核函数do_exit()
,从那里exit_notify()
和从那里do_notify_parent()
被调用,将SIGCHLD
发送到父母并致电__wake_up_parent()
。
我不明白系统调用如何停止执行并传递给 父进程,系统调用和其他进程一样吗?
sleep()
底层的系统调用将调用进程置于状态 TASK_INTERRUPTIBLE - 参见 e。 G。 Sleeping in the Kernel。之后,该进程根本不会被调度,直到被上面的__wake_up_parent()
唤醒或超时。
【讨论】:
【参考方案2】:你可以使用 gnu popen Ref gnu libc Pipe to a Subprocess fork 一个孩子。
如果您想阻止 孩子 重置 警报,这可能会有所帮助。
然后使用
alarm 和 setitimer 函数为进程在将来中断自身提供了一种机制。他们通过设置计时器来做到这一点;当定时器到期时,进程收到一个信号。
NB 你会调用上面的 before execve
可移植性注意:setitimer 和 getitimer 函数派生自 BSD Unix,而 alarm 函数 由 POSIX 指定.1 标准。 setitimer 比 alarm 更强大,但 alarm 使用更广泛。
参考libc Setting Alarm
你也可以使用 timeout Ref man timeout part of coreutils
一切顺利
【讨论】:
以上是关于信号如何中断系统调用的主要内容,如果未能解决你的问题,请参考以下文章