我在寫一個多線程的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()'應該對這個目標更可靠。我會用一個小例子來詳細說明我的答案。 –