我在写一个多线程的linux C应用程序,执行线程需要每隔4小时执行一次(可以从几秒到几小时)。目前的实现基于usleep()。但是持续时间较长是非常不准确的。第一次睡眠需要4点20分,第二次5点等等。在linux中解决这个问题的正确方法是什么?可以使用linux定时器定期调度执行线程以获得更长的时间间隔吗?Linux mutithreaded C程序<-> usleep()每小时间隔的调度精度
回答
您可以在SIGALRM
处理程序中将setitimer()
与self-pipe trick结合使用。应定期调度的线程必须在管道的读取端执行阻塞read()
。
看到这个玩具的使用示例展示了主意:
#define _POSIX_C_SOURCE 200101L
#define _BSD_SOURCE
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
int pipefd[2];
const char pipechar = 'x';
void *periodicThread(void *arg)
{
(void)arg; // unused
char c;
while (read(pipefd[0], &c, 1) > 0)
{
if (c == 'q') break;
puts("scheduled!");
}
return 0;
}
void alarmHandler(int signum)
{
(void)signum; // unused
write(pipefd[1], &pipechar, 1);
}
int main(void)
{
if (pipe(pipefd) < 0) return 1;
int rc = 1;
pthread_t thread;
if (pthread_create(&thread, 0, periodicThread, 0) != 0)
goto cleanup_pipe;
struct sigaction sa = {
.sa_handler = alarmHandler,
.sa_flags = SA_RESTART // aternatively check for EINTR after avery system call
};
if (sigaction(SIGALRM, &sa, 0) < 0) goto cleanup_thread;
// use (much) larger values here!
struct itimerval itv = {
.it_interval = {
.tv_sec = 5,
.tv_usec = 0
},
.it_value = {
.tv_sec = 5,
.tv_usec = 0
}
};
if (setitimer(ITIMER_REAL, &itv, 0) < 0) goto cleanup_thread;
rc = 0;
int c;
while ((c = getchar()) != EOF)
{
if (c == 'q') break;
}
const char pipeendchar = 'q';
cleanup_thread:
write(pipefd[1], &pipeendchar, 1);
pthread_join(thread, 0);
cleanup_pipe:
close(pipefd[0]);
close(pipefd[1]);
return rc;
}
如果你的月经变得很长,即使在struct itimerval
的time_t
领域,你可以选择一个更小的周期,只是计数的SITGALRM
数你接收。
谢谢菲利克斯。我没有使用超过秒的定时器。 sleep()系列函数的情况也是如此。这是一个特殊的案例,每个人都在谈论有关cron的工作,当它变成小时或数天。 – t3rmin4tor
@ t3rmin4tor另请参阅我的编辑。代码解释可能比一句话:) –
这是非常有帮助的。欣赏它! – t3rmin4tor
- 1. 动态调度程序间隔C#
- 2. 返回时间间隔作为C#中的双精度值#
- 3. Linux,需要精确的编程时序。调度程序唤醒程序
- 4. Kprobe在Linux调度程序和查找Linux调度程序
- 5. 石墨:每点精度的时间
- 6. 安卓N中的作业调度程序,时间间隔小于15分钟
- 7. 在精确的时间运行子程序,精度为0.1s,精度为perl
- 8. 调整小数精度,.NET
- 9. Linux,timerfd精度
- 10. C#的DataTable小数精度
- 11. FreeBSD调度程序和Linux调度程序的区别
- 12. 了解linux调度程序
- 13. threading.Timer时间精度
- 14. __time32_t时间精度?
- 15. 在每个特定时间间隔后调度r函数
- 16. 如何知道linux调度程序的时间片?
- 17. PL/SQL的间隔精度函数值
- 18. C#小数精度功能
- 19. jqPlot最小刻度间隔
- 20. Kendoui调度程序不同的时间
- 21. Drupal块中的时间调度程序
- 22. 调度程序日历日期时间选择器时间间隔
- 23. 调度自己的进程C/linux
- 24. linux的时间命令微秒或更好的精度
- 25. 阻止调用和Linux调度程序
- 26. C++:更精确的时间间隔
- 27. C#线程调度程序
- 28. 更换每隔<br/>与空间
- 29. Linux内核线程 - 调度程序
- 30. cos(atan2(y,x))与使用复数的精度<double>,C++
如果你得到20分钟的漂移,我会说这是'usleep()'参数的问题,而不是调度问题。你如何计算睡眠间隔? – myaut
类似usleep(x * 60 * 60 * 1000 * 1000),其中x是小时 – t3rmin4tor
'useconds_t'只保证值高达'1.000.000'。我认为'setitimer()'应该对这个目标更可靠。我会用一个小例子来详细说明我的答案。 –