用 kill 发送到父线程的信号是不是保证在下一条语句之前被处理?

Posted

技术标签:

【中文标题】用 kill 发送到父线程的信号是不是保证在下一条语句之前被处理?【英文标题】:Is a signal sent with kill to a parent thread guaranteed to be processed before the next statement?用 kill 发送到父线程的信号是否保证在下一条语句之前被处理? 【发布时间】:2010-04-24 02:07:16 【问题描述】:

好的,所以如果我在 linux 上的子线程中运行(如果重要,使用 pthreads),我运行以下命令

kill(getpid(), someSignal);

它将给定的信号发送到当前线程的父级。

我的问题:在运行kill() 之后的语句之前,是否保证父级将立即获得 CPU 并处理信号(如果是 SIGKILL 则终止应用程序,或者如果是其他信号则执行其他任何操作)?或者是否有可能——甚至有可能——kill() 后面的任何命令都会在父线程处理信号之前运行?

【问题讨论】:

该行实际上并没有将信号发送到“当前线程的父级”——它发送到当前的进程,这意味着可以接收到信号由 任何 进程的未阻塞信号的线程 - 包括您正在调用 kill() 的线程。 @caf 好吧,从技术上讲,线程在 linux 中是它们自己的进程,具有自己的 pid,所以这确实使事情变得复杂。但你仍然可能是对的。我对信号的处理方式并不十分了解——尤其是面对线程时。但学习仍在继续…… Linux 中的 pthreads 符合 POSIX 线程标准(因此称为“pthreads”)。进程和线程之间是有区别的,即使线程是在内核中使用单独的 task_struct 实现的。结果是getpid() 将在进程中的每个线程中返回相同的值(POSIX“进程 ID”),而gettid()(glibc 没有为其提供包装器)返回单个线程的 ID。 【参考方案1】:

不,不能保证。

一般来说,除非您使用显式同步机制(例如,phtread_mutex 或信号量),否则您不能对不同线程(或进程)中发生的事件的时间做出任何假设。

在多 CPU(或多核)系统上尤其如此,其中多个线程可以在不同的 CPU 上同时运行,但即使在单 CPU 系统上也无法保证。

【讨论】:

【参考方案2】:

信号是异步传递的,所以你不能指望处理它们的线程立即处理它们;而且,它必须做一些工作来处理它。

如果 sigprocmask() 调用已经屏蔽了所有线程中的信号,则只有在取消屏蔽后才会对信号进行操作。

信号不会发送到任何特定线程,除非您使用 sigprocmask 将它们从您不想获取它们的线程中屏蔽掉。大多数多线程程序都会这样做,因为将进程级信号传递给任意线程通常不是您想要的。

【讨论】:

【参考方案3】:

发送到进程(线程组)的信号通常可能会传递到任何线程,并且您通常无法保证处理程序会在 kill 调用返回之前完成。

如果你跑了

kill(getpid(), someSignal);

在多线程进程中,您只能确保您的 sighandler 将在 kill 返回之前运行在一个非常特定的场景中,其中 除了调用线程之外的所有线程都阻塞了someSignal(在这种情况下,sig 处理程序将从调用kill 的线程运行)。

看 http://pubs.opengroup.org/onlinepubs/009695399/functions/kill.html

如果 pid 的值导致为发送生成 sig 进程,如果 sig 没有被调用线程阻塞,如果没有 其他线程已解除阻塞或正在等待 sigwait() 函数 对于 sig,应为 sig 或至少一个未决的未阻塞信号 在 kill() 返回之前传递给发送线程。

【讨论】:

以上是关于用 kill 发送到父线程的信号是不是保证在下一条语句之前被处理?的主要内容,如果未能解决你的问题,请参考以下文章

pthread中向线程发送信号

Linux下的进程与线程—— 信号

kill信号由谁接收处理

Unix系统编程()发送信号的其他方式:raise和killpg

linux系统上信号发送和信号接收讲解

Linux进程调度的kill命令