原创 Linux 信号量sem_wait(3) (翻译 man 3)

2011-1-8 20:25 2507 6 6 分类: 工程师职场

http://blog.csdn.net/scarlettsp/archive/2010/11/22/6027769.aspx

SEM_WAIT(3)                   Linux Programmer's Manual                   SEM_WAIT(3)

NAME

       sem_wait, sem_timedwait, sem_trywait - lock a semaphore
//锁定一个信号量

SYNOPSIS

       #include 
       int sem_wait(sem_t *sem);
       int sem_trywait(sem_t *sem);
       int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
       Link with -lrt or -pthread.
   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
       sem_timedwait(): _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600

DESCRIPTION

       sem_wait() decrements (locks) the semaphore pointed to by sem.  If the
       semaphore's value is greater than zero, then the decrement proceeds, and the
       function returns, immediately.  If the semaphore currently has the value zero,
       then the call blocks until either it becomes possible to perform the decrement
       (i.e., the semaphore value rises above zero), or a signal handler interrupts
       the call.
//sem_wait() 减小(锁定)由sem指定的信号量的值.如果信号量的值比0大,那么进行减一的操作,函数立即返回.
//如果信号量当前为0值,那么调用就会一直阻塞直到或者是信号量变得可以进行减一的操作(例如,信号量的值比0大),或者是信号处理程序中断调用.
       sem_trywait() is the same as sem_wait(), except that if the decrement cannot
       be immediately performed, then call returns an error (errno set to EAGAIN)
       instead of blocking.
//sem_trywait() 和 sem_wait()是一样的,除了如果不能够对信号量立即进行减一,那么sem_trywait()就会返回一个错误(错误号是AGAIN)而不是锁定.
       sem_timedwait() is the same as sem_wait(), except that abs_timeout specifies a
       limit on the amount of time that the call should block if the decrement cannot
       be immediately performed.  The abs_timeout argument points to a structure that
       specifies an absolute timeout in seconds and nanoseconds since the Epoch,
       1970-01-01 00:00:00 +0000 (UTC).  This structure is defined as follows:
//sem_timedwait() 和 sem_wait()是一样的,除了如果减一操作不能立即执行的话,abs_timeout 指定了调用应该被阻塞的时间限制.
//abs_timeout 参数指向了一个结构体指定了由秒和纳秒组成的绝对的超时值:从1970-01-01 00:00:00 +0000纪元开始的UTC,结构体的定义如下:
           struct timespec {
               time_t tv_sec;      /* Seconds */
               long   tv_nsec;     /* Nanoseconds [0 .. 999999999] */
           };
       If the timeout has already expired by the time of the call, and the semaphore
       could not be locked immediately, then sem_timedwait() fails with a timeout
       error (errno set to ETIMEDOUT).
//如果超时值已经超过了调用规定的值,那么信号量不能被立即锁定,之后sem_timedwait() 为超时失败(error设置为ETIMEDOUT).
       If the operation can be performed immediately, then sem_timedwait() never
       fails with a timeout error, regardless of the value of abs_timeout.
       Furthermore, the validity of abs_timeout is not checked in this case.
//如果操作立即生效,那么sem_timedwait() 永远不会返回超时的错误,不管abs_timeout的值.
//更进一步的是,在这种情况下abs_timeout值的有效性都不会检查.

RETURN VALUE

       All of these functions return 0 on success; on error, the value of the
       semaphore is left unchanged, -1 is returned, and errno is set to indicate the
       error.
//所有的函数成功返回0,错误的话信号量的值不改动,返回-1.errno设定来标识错误.

ERRORS

       EINTR  The call was interrupted by a signal handler; see signal(7).
//调用被信号处理中断
       EINVAL sem is not a valid semaphore.
//sem不是有效的信号量
       The following additional error can occur for sem_trywait():
//下面的错误是sem_trywait()可能发生的:
       EAGAIN The operation could not be performed without blocking (i.e., the
              semaphore currently has the value zero).
//除了锁定无法进行别的操作(如信号量当前是0值).
       The following additional errors can occur for sem_timedwait():
//下面的错误是sem_timedwait()可能发生的:
       EINVAL The value of abs_timeout.tv_nsecs is less than 0, or greater than or
              equal to 1000 million.
//abs_timeout.tv_nsecs 的值比0小或者大于等于1000毫秒(译者注:纳秒的值不能比0小,不能比1秒大)
       ETIMEDOUT
              The call timed out before the semaphore could be locked.
//在信号量锁定之前就超时了.

CONFORMING TO

       POSIX.1-2001.

NOTES

       A signal handler always interrupts a blocked call to one of these functions,
       regardless of the use of the sigaction(2) SA_RESTART flag.
//对这些函数,信号处理程序总是会中断阻塞,不管是否使用了sigaction(2)的SA_RESTART标志位.

EXAMPLE

       The (somewhat trivial) program shown below operates on an unnamed semaphore.
       The program expects two command-line arguments.  The first argument specifies
       a seconds value that is used to set an alarm timer to generate a SIGALRM
       signal.  This handler performs a sem_post(3) to increment the semaphore that
       is being waited on in main() using sem_timedwait().  The second command-line
       argument specifies the length of the timeout, in seconds, for sem_timedwait().
       The following shows what happens on two different runs of the program:
//(有些琐碎的)程序以下展示了在一个未命名的信号量上的操作.程序请求2个命令行参数,第一个参数指定一个秒的参数来作为报警的定时器来产生SIGALRM信号.
//信号处理程序执行sem_post(3)来增加在main()函数中使用sem_wait()等待的信号量的值.第二个命令行参数指定超时的长度,为sem_timedwait()使用秒为单位.
//以下展示了程序的执行的不同效果.
           $ ./a.out 2 3
           About to call sem_timedwait()
           sem_post() from handler
           sem_getvalue() from handler; value = 1
           sem_timedwait() succeeded
           $ ./a.out 2 1
           About to call sem_timedwait()
           sem_timedwait() timed out
Program source
       #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  \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);
       }

SEE ALSO

       clock_gettime(2), sem_getvalue(3), sem_post(3), sem_overview(7), time(7)

COLOPHON

       This page is part of release 3.31 of the Linux man-pages project.  A
       description of the project, and information about reporting bugs, can be found
       at http://www.kernel.org/doc/man-pages/.
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
6
关闭 站长推荐上一条 /3 下一条