next up previous contents
下一篇: 系统调用:semctl() 上一级: 6.4.3 信号量 上一篇: 系统调用:semget()

系统调用:semop()


  SYSTEM CALL: semop();                                                          
  PROTOTYPE: int semop ( int semid, struct sembuf *sops, unsigned nsops);
    RETURNS: 0 on success (all operations performed)
             -1 on error: errno = E2BIG (nsops greater than max number of ops allowed atomically)
                                  EACCESS (permission denied)
                                  EAGAIN (IPC_NOWAIT asserted, operation could not go through)
                                  EFAULT (invalid address pointed to by sops argument)
                                  EIDRM (semaphore set was removed)
                                  EINTR (Signal received while sleeping)
                                  EINVAL (set doesn't exist, or semid is invalid)
                                  ENOMEM (SEM_UNDO asserted, not enough memory to create the
                                          undo structure necessary)
                                  ERANGE (semaphore value out of range)
  NOTES:

`semop()` 的第一个参数semget()是键值(在我们的例子中由调用semget返回)。第二个参数(sops)是指向要在信号量集上执行的操作数组的指针,而第三个参数(nsops)是该数组中操作的数量。

`sops`sops参数指向 `sembuf` 类型的数组。sembuf。此结构在linux/sem.h中声明如下


        /* semop system call takes an array of these */
        struct sembuf {
                ushort  sem_num;        /* semaphore index in array */
                short   sem_op;         /* semaphore operation */
                short   sem_flg;        /* operation flags */
        };

sem_num

您希望处理的信号量编号

sem_op

要执行的操作(正数、负数或零)

sem_flg

操作标志

如果 `sem_op`sem_op为负数,则其值将从信号量中减去。这与获取信号量控制或监视访问的资源相关。如果未指定 IPC_NOWAIT,则调用进程将休眠,直到信号量中可用的资源量达到请求的数量(另一个进程已释放了一些资源)。

如果 `sem_op`sem_op如果 `sem_op` 为正数,则其值将添加到信号量中。这与将资源返回到应用程序的信号量集相关。当不再需要资源时,应始终将资源返回到信号量集!

最后,如果 `sem_op`sem_op为零 (0),则调用进程将 sleep(),直到信号量的值为 0。这与等待信号量达到 100% 利用率相关。一个很好的例子是具有超级用户权限的守护进程,如果信号量集达到完全利用率,它可以动态调整信号量集的大小。

为了解释 `semop`semop调用,让我们回顾一下我们的打印室场景。假设只有一台打印机,一次只能处理一个作业。我们创建一个信号量集,其中只有一个信号量(只有一台打印机),并将该信号量初始化为值 1(一次只能处理一个作业)。

每次我们想要向这台打印机发送作业时,我们需要首先确保资源可用。我们通过尝试从信号量中获取一个单元来做到这一点。让我们加载一个 sembuf 数组来执行操作


        struct sembuf sem_lock = { 0, -1, IPC_NOWAIT };

上面初始化的结构的翻译表明,值“-1”将被添加到信号量集中编号为 0 的信号量中。换句话说,将从我们集合中唯一的信号量(第 0 个成员)中获取一个单元的资源。指定了 IPC_NOWAIT,因此调用将立即进行,或者如果另一个打印作业当前正在打印,则调用将失败。以下是使用此初始化的示例sembuf结构与semop系统调用


        if((semop(sid, &sem_lock, 1) == -1)
                perror("semop");

第三个参数(nsops)表示我们只执行一个 (1) 操作(只有一个sembuf结构在我们的操作数组中)。 `sid`sid参数是我们信号量集的 IPC 标识符。

当我们的打印作业完成后,我们必须将资源返回到信号量集,以便其他人可以使用打印机。


        struct sembuf sem_unlock = { 0, 1, IPC_NOWAIT };

上面初始化的结构的翻译表明,值“1”将被添加到信号量集中编号为 0 的信号量中。换句话说,一个单元的资源将返回到集合中。


next up previous contents
下一篇: 系统调用:semctl() 上一级: 6.4.3 信号量 上一篇: 系统调用:semget()

转换于
1996 年 3 月 29 日星期五 14:43:04 EST