进程间通信之: 信号量
cmd:指定对信号量的各种操作,当使用单个信号量(而不是信号量集)时,常用的有以下几种: IPC_STAT:获得该信号量(或者信号量集合)的semid_ds结构,并存放在由第4个参数arg的buf指向的semid_ds结构中。semid_ds是在系统中描述信号量的数据结构。 IPC_SETVAL:将信号量值设置为arg的val值 IPC_GETVAL:返回信号量的当前值 IPC_RMID:从系统中,删除信号量(或者信号量集) | |
arg:是union semnn结构,该结构可能在某些系统中并不给出定义,此时必须由程序员自己定义 union semun { int val; struct semid_ds *buf; unsigned short *array; } | |
函数返回值 | 成功:根据cmd值的不同而返回不同的值 IPC_STAT、IPC_SETVAL、IPC_RMID:返回0 IPC_GETVAL:返回信号量的当前值 |
出错:-1 |
表8.19列举了semop()函数的语法要点。
表8.19 semop()函数语法要点
所需头文件 | #include <sys/types.h> |
函数原型 | int semop(int semid, struct sembuf *sops, size_t nsops) |
函数传入值 | semid:semget()函数返回的信号量标识符 |
sops:指向信号量操作数组,一个数组包括以下成员: struct sembuf { short sem_num; /* 信号量编号,使用单个信号量时,通常取值为0 */ short sem_op; /* 信号量操作:取值为-1则表示P操作,取值为+1则表示V操作*/ short sem_flg; /* 通常设置为SEM_UNDO。这样在进程没释放信号量而退出时,系统自动 释放该进程中未释放的信号量 */ } | |
nsops:操作数组sops中的操作个数(元素数目),通常取值为1(一个操作) | |
函数返回值 | 成功:信号量标识符,在信号量的其他函数中都会使用该值 |
出错:-1 |
3.使用实例
本实例说明信号量的概念以及基本用法。在实例程序中,首先创建一个子进程,接下来使用信号量来控制两个进程(父子进程)之间的执行顺序。
因为信号量相关的函数调用接口比较复杂,我们可以将它们封装成二维单个信号量的几个基本函数。它们分别为信号量初始化函数(或者信号量赋值函数)init_sem()、P操作函数sem_p()、V操作函数sem_v()以及删除信号量的函数del_sem()等,具体实现如下所示:
/* sem_com.c */
#include "sem_com.h"
/* 信号量初始化(赋值)函数*/
int init_sem(int sem_id, int init_value)
{
union semun sem_union;
sem_union.val = init_value; /* init_value为初始值 */
if (semctl(sem_id, 0, SETVAL, sem_union) == -1)
{
perror("Initialize semaphore");
return -1;
}
return 0;
}
/* 从系统中删除信号量的函数 */
int del_sem(int sem_id)
{
union semun sem_union;
if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1)
{
perror("Delete semaphore");
return -1;
}
}
/* P操作函数 */
int sem_p(int sem_id)
{
struct sembuf sem_b;
sem_b.sem_num = 0; /* 单个信号量的编号应该为0 */
sem_b.sem_op = -1; /* 表示P操作 */
sem_b.sem_flg = SEM_UNDO; /* 系统自动释放将会在系统中残留的信号量*/
if (semop(sem_id, &sem_b, 1) == -1)
{
perror("P operation");
return -1;
}
return 0;
}
/* V操作函数*/
int sem_v(int sem_id)
{
struct sembuf sem_b;
sem_b.sem_num = 0; /* 单个信号量的编号应该为0 */
sem_b.sem_op = 1; /* 表示V操作 */
sem_b.sem_flg = SEM_UNDO; /* 系统自动释放将会在系统中残留的信号量*/
if (semop(sem_id, &sem_b, 1) == -1)
{
perror("V operation");
return -1;
}
return 0;
}
现在我们调用这些简单易用的接口,可以轻松解决控制两个进程之间的执行顺序的同步问题。实现代码如下所示:
/* fork.c */
#include <sys/types.h> #inclu
进程间通信 信号量 Linux semget 操作系统 相关文章:
- 进程间通信之: 共享内存(08-13)
- 进程间通信之:实验内容(08-13)
- 《嵌入式Linux应用程序开发标准教程》(第2版)(09-30)
- 进程间通信之:消息队列(09-13)
- 进程间通信之:本章小结及思考与练习(09-13)
- 硬件实时操作系统信号量管理的设计与实现(01-23)