#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\n", 24); if (sem_post(&sem) == -1) { write(STDERR_FILENO, "sem_post() failed\n", 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>\n", 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()\n"); 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\n"); else perror("sem_timedwait"); } else printf("sem_timedwait() succeeded\n"); 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來判斷呢。