我想在使用NPTL的libc的linux 2.6+中的multithreading进程中使用setitimer()
(或更less的可能性, alarm()
)。 哪个线程将从内核接收sigalarm (SIGALRM)
?
谢谢。
2014-04更新:如何在multithreading程序中设置setitimer()
,如果我想编写一个类似gperftools的cpuprofile的分析工具; 但在我的工具,我想支持dynamic链接的程序(所以有可能注入我自己的库到init分析)和静态链接的程序(没有做^^^^^^的可能性)。
我当前的分析工具在setitimer
fork()
和exec()
之前设置setitimer
,它还使用ptrace
来控制目标程序并劫持由setitimer
生成的SIGPROF / SIGVPROF / SIGALRM。 我不知道它是如何与multithreading程序一起工作的。
从信号(7)手册页:
处理导向的信号可以被传送到当前没有信号被阻塞的线程中的任何一个。 如果不止一个线程的信号被解除阻塞,那么内核会选择一个任意的线程来传递信号。
现在, 闹钟(2)手册页说:
alarm()将以秒为单位安排一个SIGALRM信号传递给进程。
所以,信号被传递到一个进程 (一个信号也可能指向某个线程),因此你不知道哪个线程会收到它。
和setitimer(2)一样 :
当任何定时器到期时,一个信号被发送到进程,并且定时器(潜在地)重新启动。
除了一个线程,你可以在所有的线程中阻塞SIGALARM
,那么你可以肯定它将被传递给唯一的线程。 假设你正在使用pthreads,你可以用pthread_sigmask()来阻塞信号。
在2010年的LKML有一个有趣的话题https://lkml.org/lkml/2010/4/11/81:“setitimer 与线程:SIGALRM返回到哪个线程?(进程主或独立子) ”由Frantisek Rysanek cz )。 作者说setitimer
至少在Fedora 5之前使用per-thread信号:
…
setitimer()
具有每个线程的粒度。 它用来从定时器向调用setitimer()
的特定线程传递一个SIGALRM
。
但在最近的Fedora中,行为发生了变化( “man pthreads”,…“线程不共享间隔定时器(固定在2.6.12内核中)” )
在这个话题中,Andi Kleen(英特尔) 建议切换到 “ POSIX定时器( timer_create
) ”; 在ML线程中, Davide Libenzi建议在非古代Linux上使用timerfd
(timerfd_create,timerfd_settime)。