休眠在线程中(C / POSIX 线程)
我正在开发一个使用 POSIX 线程 的多线程应用程序。我正在使用线程来执行定期工作,为此我使用 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();
}
这是用于从主线程停止(和优雅地关闭)给定线程的伪函数:
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);
}
实现的便捷方法是什么我的目标?我是否必须使用条件变量或者可以使用 sleep() 变体来做到这一点?
I am developing a multithreaded application that makes use of POSIX Threads. I am using threads for doing a periodical job 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:
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
将
select()
与 FIFO 或套接字一起使用,您可以通过戳它来唤醒它。USe
select()
with a FIFO or socket that you can poke in order to wake it up.您还可以使用信号量进行睡眠(这实际上是它们的真正目的)。
线程中的
sema_wait
和主线程中的sema_post
。它简单、干净、便携。这是详细介绍该过程的文章的链接:http://www.netrino.com/node/202
You can also sleep with a semaphore (it's in fact their real purpose).
a
sema_wait
in your thread and asema_post
in 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
SIGALRM 终止整个应用程序的原因是您可能尚未为其注册信号处理程序。 SIGALRM 的默认操作是内核终止进程,因此如果
usleep
以不使用 SIGALRM 的方式实现(使用nanosleep
或轮询函数之一)例如,超时)则usleep
将不会注册处理程序或以其他方式更改信号的默认配置。应该足以避免杀死你的程序,尽管你应该研究更复杂的 sigaction 函数而不是 signal ,因为它允许更多的控制并且在不同平台上表现得更一致。
如果您随后尝试在使用 SIGALRM 实现
usleep
或sleep
的系统上使用代码,这可能会导致问题,因此您可能不想使用标准这些的库版本,并使用在所有平台上具有更可预测实现的函数(可能是nanosleep
的薄包装,提供您想要的接口)。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
usleep
is implemented in a manner that does not use SIGALRM (usingnanosleep
or one of the polling functions with a timeout, for instance) thenusleep
would not have registered a handler or otherwise changed the default disposition of the signal.should be enough to keep from killing your program, though you should look into the more complicated
sigaction
function rather thansignal
since it allows for more control and behaves more consistently across different platforms.This is may cause problems if you then try to use the code on a system that does use SIGALRM to implement
usleep
orsleep
, 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 aroundnanosleep
that provides the interface you want).我们使用 pthread_cond_timedwait 对条件变量进行等待,并设置超时。
当我们想要关闭时,我们设置一个“关闭”变量并执行 pthread_cond_broadcast
We use a wait on a condition variable with a timeout using pthread_cond_timedwait
When we want to shutdown we set a 'shuting down' variable and do a pthread_cond_broadcast
作为
select
的替代方案,还可以使用 pthread 条件变量(请参阅pthread_cond_init
、pthread_cond_wait
和pthread_cond_signal
>)、SysV 信号量或 POSIX 信号量。所有这些都比 usleep 更适合事件处理线程。As an alternative to
select
, it is also possible to use pthread condition variables (seepthread_cond_init
,pthread_cond_wait
, andpthread_cond_signal
), SysV semaphores, or POSIX semaphores. All of those are a better fit than usleep for an event-processing thread.从引用的手册页来看,您似乎正在 Linux 上运行。
您应该能够使用 nanosleep 并中断由应用程序确定的 (SIGRTMIN+x) 子进程。 Nanosleep 具有被信号中断并返回其应该睡眠的剩余时间的功能。如果您需要较长时间的睡眠,您也可以只使用睡眠。
nanosleep(2)
signal(7)
上面提到的任何类型的 IPC 也可以帮助你解决这个问题。
编辑:看起来您已经在这样做了,除非您应该使用不会对程序产生外部影响的信号。任何睡眠功能都应该被非阻塞信号中断。实时信号旨在按每个应用程序使用。
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.
nanosleep(2)
signal(7)
Any sort of IPC mentioned above could also help you solve this problem.
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.
有很多方法可以做到这一点:
eventfd(2)
来替换此处的管道)pthread_sigmask(3)
There's a number of ways to do this:
eventfd(2)
to replace pipes here)pthread_sigmask(3)
也许你需要弄乱信号掩码,或者信号可能无法离开睡眠状态......我不知道。我不知道可以使用 sigwait() 或 sigtimedwait()。我们使用 pthread_kill 来唤醒线程,但我们使用 sigwait 来睡眠它们......而不是 usleep。这是我发现唤醒执行此操作的最快方法(根据我的测试,比等待 pthread_cond 快 40-50 倍)。
我们在创建线程之前执行此操作:
创建的每个线程都会继承此掩码。我对面具有点困惑。您要么告诉系统不要对某些信号执行任何操作,要么告诉系统您正在处理某些信号......我不知道。其他人可以介入并帮助我们。如果我更好地了解掩码的工作原理,我也许可以告诉您,您可以将上述代码粘贴到 ThreadProc 中。另外,我不确定 SIGSEGV 是否有必要。
然后一个线程调用它来睡眠自己:
然后你这样做来唤醒一个线程:
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.)
We do this before creating threads:
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.
Then a thread calls this to sleep itself:
Then you do this to wake a thread: