#include <semaphore.h> int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout); Link with -pthread.
对于这个函数,主要在于abs_timeout这个参数。一开始我以为是传入需要等待的时间。像这样:
struct timespec ts; ts.tv_nsec = 1000; ts.tv_sec = 10; sem_timedwait(p_sem, &ts);
意思是我希望10秒1000纳秒才超时。结果,函数立即返回。网上查一下资料,才知道我错得多么离谱。这个abs_timeout竟然是UTC时间戳。看下面的代码http://linux.die.net/man/3/sem_timedwait:
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <semaphore.h> #include <time.h> #include <assert.h> #include <errno.h> #include <signal.h> sem_t sem; #define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0) static void handler(int sig) { write(STDOUT_FILENO, "sem_post() from handler ", 24); if (sem_post(&sem) == -1) { write(STDERR_FILENO, "sem_post() failed ", 18); _exit(EXIT_FAILURE); } } int main(int argc, char *argv[]) { struct sigaction sa; struct timespec ts; int s; if (argc != 3) { fprintf(stderr, "Usage: %s <alarm-secs> <wait-secs> ", argv[0]); exit(EXIT_FAILURE); } if (sem_init(&sem, 0, 0) == -1) handle_error("sem_init"); /* Establish SIGALRM handler; set alarm timer using argv[1] */ sa.sa_handler = handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if (sigaction(SIGALRM, &sa, NULL) == -1) handle_error("sigaction"); alarm(atoi(argv[1])); /* Calculate relative interval as current time plus number of seconds given argv[2] */ if (clock_gettime(CLOCK_REALTIME, &ts) == -1) handle_error("clock_gettime"); ts.tv_sec += atoi(argv[2]); printf("main() about to call sem_timedwait() "); while ((s = sem_timedwait(&sem, &ts)) == -1 && errno == EINTR) continue; /* Restart if interrupted by handler */ /* Check what happened */ if (s == -1) { if (errno == ETIMEDOUT) printf("sem_timedwait() timed out "); else perror("sem_timedwait"); } else printf("sem_timedwait() succeeded "); exit((s == 0) ? EXIT_SUCCESS : EXIT_FAILURE); }
在这段代码中,他没有处理溢出,下面是我的代码:
int32 CSeamphoreLock::time_lock( int32 nano_sec,int32 sec ) { struct timespec ts; if ( clock_gettime( CLOCK_REALTIME,&ts ) < 0 ) return -1; ts.tv_sec += sec; ts.tv_nsec += nano_sec; //#define NSECTOSEC 1000000000 ts.tv_sec += ts.tv_nsec/NSECTOSEC; //Nanoseconds [0 .. 999999999] ts.tv_nsec = ts.tv_nsec%NSECTOSEC; return sem_timedwait( m_psem,&ts ); }
PS:居然用的时间戳,如果正在等待的时候管理员调整时间会不会让某个程序出问题呢??为什么不用clock_gettime的CLOCK_MONOTONIC来判断呢。