C语言 在线程中休眠(C / POSIX 线程)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4016789/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sleeping in a Thread (C / POSIX Threads)
提问by Emre Yazici
I am developing a multithreaded application that makes use of POSIX Threads. I am using threads for doing a periodicaljob and for that purpose I am using usleep(3)to suspend thread execution. My question is how can I cancel usleep() timer from the main thread, I tried pthread_kill(thread, SIGALRM)but it has a global effect which results in termination of the main application (by default). Here is my pseudo code:
我正在开发一个使用POSIX Threads的多线程应用程序。我正在使用线程来执行定期工作,为此我使用usleep(3)来暂停线程执行。我的问题是如何从主线程取消 usleep() 计时器,我尝试过,pthread_kill(thread, SIGALRM)但它具有全局效果,导致主应用程序终止(默认情况下)。这是我的伪代码:
void threaded_task(void *ptr) {
initialize();
while(running) {
do_the_work();
usleep(some_interval);
}
clean_up();
release_resources();
}
And here is the pseudo function that is used to stop (and gracefully shutdown) given thread from the main thread:
这是用于从主线程停止(并正常关闭)给定线程的伪函数:
void stop_thread(pthread_t thread) {
set_running_state(thread, 0); // Actually I use mutex staff
// TODO: Cancel sleep timer so that I will not wait for nothing.
// Wait for task to finish possibly running work and clean up
pthread_join(thread, NULL);
}
What is the convenient way to achieve my goal? Do I have to use conditional variables or can I do this using sleep() variants?
实现我的目标的便捷方法是什么?我必须使用条件变量还是可以使用 sleep() 变体来做到这一点?
采纳答案by Ignacio Vazquez-Abrams
USe select()with a FIFO or socket that you can poke in order to wake it up.
使用select()与FIFO或插座,你可以为了唤醒它戳。
回答by Patrick Schlüter
You can also sleep with a semaphore (it's in fact their real purpose).
你也可以用信号量睡觉(这实际上是它们的真正目的)。
a sema_waitin your thread and a sema_postin your main thread. It's easy, it's clean, it's portable. Here a link to an article detailing the procedure:
http://www.netrino.com/node/202
asema_wait在您的线程中, asema_post在您的主线程中。它很容易,很干净,很便携。这是详细介绍该过程的文章的链接:http:
//www.netrino.com/node/202
回答by nategoose
The reason that SIGALRM is killing the entire application is that you probably haven't registered a signal handler for it. The default action for SIGALRM is for the kernel to terminate the process, so if usleepis implemented in a manner that does not use SIGALRM (using nanosleepor one of the polling functions with a timeout, for instance) then usleepwould not have registered a handler or otherwise changed the default disposition of the signal.
SIGALRM 杀死整个应用程序的原因是您可能没有为它注册信号处理程序。SIGALRM 的默认操作是让内核终止进程,因此如果usleep以不使用 SIGALRM 的方式实现(例如,使用nanosleep或 具有超时的轮询函数之一),则usleep不会注册处理程序或以其他方式更改了信号的默认配置。
void handle_alrm(int sig) {
}
...
int main(void) {
signal(SIGALRM, handle_alrm);
...
should be enough to keep from killing your program, though you should look into the more complicated sigactionfunction rather than signalsince it allows for more control and behaves more consistently across different platforms.
应该足以避免杀死您的程序,尽管您应该研究更复杂的sigaction功能,而不是signal因为它允许更多控制并且在不同平台上的行为更加一致。
This is may cause problems if you then try to use the code on a system that does use SIGALRM to implement usleepor sleep, so you may want to just not use the standard library versions of those and use functions that have a more predictable implementation across all platforms (possibly a thin wrapper around nanosleepthat provides the interface you want).
如果您随后尝试在确实使用 SIGALRM 实现usleepor的系统上使用代码,这可能会导致问题sleep,因此您可能只想不使用那些标准库版本并使用在所有平台上具有更可预测实现的函数(可能是一个薄包装器nanosleep,可提供您想要的界面)。
回答by pm100
We use a wait on a condition variable with a timeout using pthread_cond_timedwait
我们使用 pthread_cond_timedwait 对带有超时的条件变量进行等待
When we want to shutdown we set a 'shuting down' variable and do a pthread_cond_broadcast
当我们想关闭时,我们设置一个“关闭”变量并执行 pthread_cond_broadcast
回答by johnnycrash
Maybe you need to mess with the signal mask or maybe signals can't get out of usleep...I don't know. I don know that could use sigwait() or sigtimedwait(). We use pthread_kill to wake threads, but we sleep them using sigwait....not usleep. This is the fastest way I have found to wake do this (40-50x faster than waiting on a pthread_cond according to my tests.)
也许您需要弄乱信号掩码,或者信号无法摆脱 usleep ......我不知道。我不知道可以使用 sigwait() 或 sigtimedwait()。我们使用 pthread_kill 来唤醒线程,但我们使用 sigwait ....而不是 usleep 来休眠它们。这是我发现唤醒执行此操作的最快方法(根据我的测试,比等待 pthread_cond 快 40-50 倍。)
We do this before creating threads:
我们在创建线程之前这样做:
int fSigSet;
sigemptyset(&fSigSet);
sigaddset(&fSigSet, SIGUSR1);
sigaddset(&fSigSet, SIGSEGV);
pthread_sigmask(SIG_BLOCK, &fSigSet, NULL);
Every thread created inherits this mask. I get a little confused with the masks. You are either telling the system to not do anything for certain signals or maybe you are telling the system that you are handling some signals...I don't know. Someone else can pipe in and help us out. If I new better how the masks worked, I might be able to tell you that you could just stick the above code in your ThreadProc. Also, I'm not sure if SIGSEGV is necessary.
创建的每个线程都继承此掩码。我对面具有点困惑。您要么告诉系统不对某些信号做任何事情,要么告诉系统您正在处理某些信号......我不知道。其他人可以通过管道来帮助我们。如果我更好地了解掩码的工作方式,我可能会告诉您,您可以将上述代码粘贴到您的 ThreadProc 中。另外,我不确定是否需要 SIGSEGV。
Then a thread calls this to sleep itself:
然后一个线程调用它来休眠自己:
int fSigReceived;
// next line sleeps the thread
sigwait(&fSigSet, &fSigReceived); // assuming you saved fSigSet from above...
// you get here when the thread is woken up by the signal
// you can check fSigReceived if you care what signal you got.
Then you do this to wake a thread:
然后你这样做来唤醒一个线程:
thread_kill(pThread, SIGUSR1);
回答by Ray
As an alternative to select, it is also possible to use pthread condition variables (see pthread_cond_init, pthread_cond_wait, and pthread_cond_signal), SysV semaphores, or POSIX semaphores. All of those are a better fit than usleep for an event-processing thread.
作为替代select,也可以使用并行线程状态变量(参见pthread_cond_init,pthread_cond_wait和pthread_cond_signal),SysV的信号量或POSIX信号量。所有这些都比 usleep 更适合事件处理线程。
回答by CtRanger
It looks like you are running on Linux from the referenced man page. You should be able to use nanosleep and interupt with a application determined (SIGRTMIN+x) to the child process. Nanosleep has functionality to be interrupted by signals and return the remaining time it was supposed to have slept. You could also just use sleep if you are using larger periods of time to sleep.
从引用的手册页看来,您正在 Linux 上运行。您应该能够使用 nanosleep 和 interupt 与确定的应用程序 (SIGRTMIN+x) 到子进程。Nanosleep 具有被信号中断并返回它应该睡觉的剩余时间的功能。如果您使用更长的睡眠时间,您也可以只使用睡眠。
Any sort of IPC mentioned above could also help you solve this problem.
上面提到的任何类型的 IPC 也可以帮助您解决这个问题。
EDIT:It looks like you are already doing this except you should be using a signal that won't have an external effects on the program. Any of the sleep functions should be interrupted by a non blocked signal. The real-time signals are meant to be used on a per application basis.
编辑:看起来你已经在这样做了,除非你应该使用一个不会对程序产生外部影响的信号。任何睡眠功能都应该被非阻塞信号中断。实时信号旨在用于每个应用程序。
回答by Nikolai Fetissov
There's a number of ways to do this:
有多种方法可以做到这一点:
- Use self-pipe trick @Ignacio mentions (Linux provides handy, but not portable,
eventfd(2)to replace pipes here) - Connect threads via blocking queues built around mutexes and conditional variables, wait on empty queue, wakeup on item in the queue
- Block signals in main thread before starting other threads, wait for signal, wake on signal - see
pthread_sigmask(3)
- 使用@Ignacio 提到的自管道技巧(Linux 提供了方便但不可移植的
eventfd(2)管道来替换此处的管道) - 通过围绕互斥体和条件变量构建的阻塞队列连接线程,等待空队列,唤醒队列中的项目
- 在启动其他线程之前阻止主线程中的信号,等待信号,在信号时唤醒 - 见
pthread_sigmask(3)

