【问题标题】:Does kill(SIGSTOP) take effect by the time kill() returns?kill(SIGSTOP) 是否在 kill() 返回时生效?
【发布时间】:2019-11-18 17:21:02
【问题描述】:

假设我有一个父进程和一个子进程(以例如 fork() 或 clone() 开头)在 Linux 上运行。进一步假设有一些共享内存,父母和孩子都可以修改。

在父进程的上下文中,我想停止子进程并知道它实际上已经停止,而且子进程所做的任何共享内存写入对父进程都是可见的(包括任何同步或缓存刷新这可能需要在多处理器系统中)。

This answer,它谈到使用 kill(SIGSTOP) 停止子进程,包含一个有趣的花絮:

当第一次 kill() 调用成功时,您可以放心地假定子进程已停止。

这句话真的是真的吗?如果是的话,谁能解释一下,或者指点我一些更详细的文档(例如 Linux 联机帮助页)?否则,我是否可以使用另一种机制来确保子进程完全停止并且不会再对共享内存进行任何写入?

我正在想象以下内容:

  1. 父级发送不同的信号(例如 SIGUSR1),子级可以处理该信号
  2. 孩子处理 SIGUSR1 并在信号处理程序中执行类似 pthread_cond_wait() 的操作以安全地“停止”(尽管从内核角度来看仍在运行)——这在我的脑海中还没有完全充实,只是一个想法

如果这个问题已经有了既定的解决方案,我想避免重新发明轮子。注意子进程需要被抢先停止;在这种情况下,向子进程添加某种主动轮询不是一种选择。

如果它只存在于 Linux 上,pthread_suspend() 将是完美的......

【问题讨论】:

  • 子进程在信号处理程序中执行一些互斥/cond 魔术,让父进程知道它已停止 停止的进程无法执行任何操作 - 根据定义。
  • "父进程发送一个不同的信号(例如 SIGUSR1)" 所以从内核的角度来看,子进程不会真正停止,只是在等待,例如pthread_cond_wait() -- 我将编辑问题以澄清

标签: linux unix signals child-process


【解决方案1】:

听起来您确实应该使用带有处理程序的自定义信号,而不是 sigstop。

很少关心孩子的状态,例如可以从单个非原子 64 位写入中存储 32 位,或者在两个依赖写入之间进行逻辑捕获。

即使您是,POSIX 也允许操作系统不让共享写入立即对其他进程可见,因此孩子应该有机会调用msync 以获得可移植性,以确保写入完全同步。

【讨论】:

  • 谢谢,这是一个很好的建议,我最初接受它作为答案——虽然 pilcrow 更直接地回答了原始问题。
【解决方案2】:

POSIX documentation on Signal Concepts 强烈建议但未明确说明目标进程将在kill() 返回时停止:

当导致信号的事件首次发生时,信号被称为为(或发送给)进程或线程“生成”...此类事件的示例包括...调用 kill( )sigqueue() 函数。

文档很难区分信号生成传递(当信号动作生效时)或接受。不幸的是,它有时提到在生成时响应停止信号而采取的行动,有时在交付时。鉴于某些事情必须在生成时发生本身,我同意目标进程必须在您的调用返回时停止。

但是,以另一个系统调用为代价,您可以肯定。由于您的设计中有父/子关系,您可以waitpid()/WUNTRACED 接收您的子进程确实已停止的通知。

编辑

请参阅 that other guy 中的另一个 answer [原文如此],了解您可能想要这样做的原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-17
    • 2012-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-15
    • 2017-09-29
    • 1970-01-01
    相关资源
    最近更新 更多