信号如何中断系统调用

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 一个孩子。

如果您想阻止 孩子 重置 警报,这可能会有所帮助。

然后使用

alarmsetitimer 函数为进程在将来中断自身提供了一种机制。他们通过设置计时器来做到这一点;当定时器到期时,进程收到一个信号。

NB 你会调用上面的 before execve

可移植性注意:setitimergetitimer 函数派生自 BSD Unix,而 alarm 函数 由 POSIX 指定.1 标准。 setitimeralarm 更强大,但 alarm 使用更广泛

参考libc Setting Alarm

你也可以使用 timeout Ref man timeout part of coreutils

一切顺利

【讨论】:

以上是关于信号如何中断系统调用的主要内容,如果未能解决你的问题,请参考以下文章

低速系统调用的信号中断

Linux中断的系统调用

信号中断阻塞模式下的发送方法

linux内核中断体系结构

进程与信号之中断系统调用

中断异常和系统调用