用 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 发送到父线程的信号是不是保证在下一条语句之前被处理?的主要内容,如果未能解决你的问题,请参考以下文章