几次运行后,POSIX计时器挂起

我在程序的主要function中创build了一个POSIX计时器。 主程序的每个线程都设置定时器,以便在它到期时,信号处理程序更新一个variables,唤醒同一进程的下一个线程。

计时器大多数时间都工作正常,但并不总是如此。 有时在其他运行中完成全部执行,则挂起。 可能的原因是什么? 我的怀疑是与信号传递有关的。

这里是代码

#define _GNU_SOURCE #define _POSIX_C_SOURCE 199309 #include <sched.h> #include <unistd.h> #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h> #include <signal.h> #include <errno.h> #include <semaphore.h> #include <sys/stat.h> #include <fcntl.h> #include <syscall.h> #define NUM_THREADS 10 #define CLOCKID CLOCK_REALTIME #define SIG SIGUSR1 int ret; timer_t timerid; struct sigevent sev; struct itimerspec its; long long freq_nanosecs; sigset_t mask; struct sigaction sa; sem_t sem[NUM_THREADS]; sem_t mute; pthread_t tid[NUM_THREADS]; int state = 0; static void handler(int sig,siginfo_t *si,void *uc) { ret = sem_post(&sem[(state+1)%NUM_THREADS]); if (ret) { printf("Error in Sem Postn"); } state++; } void *threadA(void *data_) { int i = 0,s,n,value; long int loopNum; int turn = (intptr_t)data_; struct timespec tval_result,tval_result2; int sid = syscall(SYS_gettid); FILE *fp; fp=fopen("ipc.out","a"); fprintf(fp,"thread_%d %dn",turn,sid); fclose(fp); int counter=0; while(1) { ret = sem_wait(&sem[turn]); if (ret) { printf("Error in Sem Postn"); } //printf("Thread # -> %dn",turn); its.it_value.tv_sec = 0; its.it_value.tv_nsec = 14000; its.it_interval.tv_sec = 0; its.it_interval.tv_nsec = 0; ret = timer_settime(timerid,&its,NULL); if ( ret < 0 ) perror("timer_settime"); // Some heavy work counter++; if(counter==100) break; } printf("finished %dn",turn); } int main(int argc,char *argv[]) { int data = 0; int err,i; sa.sa_flags = SA_RESTART; sa.sa_sigaction = handler; sigemptyset(&sa.sa_mask); sigaction(SIG,&sa,NULL); sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = SIG; sev.sigev_value.sival_ptr = &timerid; ret = timer_create(CLOCKID,&sev,&timerid); if ( ret < 0 ) perror("timer_create"); sem_init(&sem[0],1); for ( i = 1; i < NUM_THREADS; ++i) { sem_init(&sem[i],0); } while(data < NUM_THREADS) { //create our threads err = pthread_create(&tid[data],NULL,threadA,(void *)(intptr_t)data); if(err != 0) printf("ncan't create thread :[%s]",strerror(err)); data++; } pthread_exit(NULL); }

据此,这个程序应该打印

64位Linux上的高分辨率定时器支持

Linux是否为应用程序提供单调递增的时钟?

Android / Linux线程join超时

Linux,timerfd的准确性

如何在Linux中创build高分辨率定时器来衡量程序性能

finished 0 finished 1 finished 2 finished 3 finished 4 finished 5 finished 6 finished 7 finished 8 finished 9

有些时候这样打印,但大部分时间,程序挂起。

定时器运行在Windows窗体中的状态

错误:“struct sigevent”没有成员名为“sigev_notify_thread_id”

如何让我的系统支持纳秒精度

Windows服务:调用线程不能访问这个对象,因为不同的线程拥有它

更改linux内核定时器

信号处理程序有一个竞争条件。 只要sem_post被调用,其他线程中的一个就可以开始运行,并且它的计时器可以在当前信号处理程序完成之前触发。 这将导致信号处理程序在另一个线程中被再次调用在这一点上, state还没有被第一个线程增加,因此第二个信号处理程序的调用最终将调用错误的信号量的sem_post 。

解决这个问题的一个方法是在调用sem_post之前确保state是递增的:

static void handler(int sig,void *uc) { state++; ret = sem_post(&sem[(state)%NUM_THREADS]); if (ret) { printf("Error in Sem Postn"); } }

请注意,此解决方案仍然包含一个问题。 它不能确保printf调用的顺序是正确的。

相关文章

本篇内容主要讲解“gitee如何上传代码”,感兴趣的朋友不妨来...
这篇“从gitee上下的代码如何用”文章的知识点大部分人都不太...
这篇文章主要介绍“gitee如何下载仓库里的项目”,在日常操作...
本篇内容主要讲解“怎么在Gitee上更新代码”,感兴趣的朋友不...
本文小编为大家详细介绍“怎么将工程托管到gitee”,内容详细...
这篇文章主要介绍了gitee中图片大小如何调整的相关知识,内容...