学习笔记——进程通信IPC之信号量

来源:互联网 发布:sql删除表中数据 编辑:程序博客网 时间:2024/06/04 17:48

      上节学习了进程间利用共享内存,进行通信。利用共享内存通信非常方便,高效,每个进程都可往共享内存里读写数据,但是并发的进程间的执行顺序是我们无法控制的,这样就可能出现诸如在读取信息之前覆盖内存空间等竞争条件。我们就需要一种机制来协调我们并发进程访问共享内存,以避免竞争状态的出现。

      Linux提供一个用于进程同步的信号量(进程信号量或称为System V信号量)。

 

包含信号量操作函数声明以及一些宏定义的头文件:

 

 

  • 与用于创建,销毁共享内存的shmget和shmctl类似,系统调用semget和semctl负责创建,释放信号量。

 

 

key参数、semflg参数与shmget里的第一个、第三个参数意思是一样的。

 

nsems参数是指定需要的信号量的数目。我们自己经常只是用到一个信号量,所以它的值几乎总是1。

当通过指定正确的键值来获取已存在的信号量的标识符是,可以把 semns 的值设为 0。

 

该函数调用成功返回 信号量 标识符,失败返回-1。

 

  • semctl 信号量管理函数

 

semctl 可以用于对信号量的初始化设置,释放删除,获取信号信息、当前的值等其他管理功能。

 

semid 是由semget返回的信号量标识符。

sem_num 上面说过semget函数的第二个参数是指定创建的信号量的数目,也就是一组信号量,所以对信号量的操作分为对单个的操作和对整个信号量组进行操作,不同的操作sem_num参数所代表的意思是不一样的。

 

对单个信号量进行操作时,sem_num表示对第几个信号量进行操作,0表示信号量组里第一个信号量(与数组一样从0开始)。

一般我们只是用到一个信号量,信号量组里只有一个信号量,sem_num的值可以是0,即对信号量组第0个信号量管理,表示这是第一个也是唯一个信号量。

 

对信号量组进行操作时,sem_num表示这个组里信号量的数目。

我们只创建了一个信号量时,用semctl函数操作信号时,sem_num表示数目时,值就是1。

 

 

 

第四个参数是union semun的结构:(自己定义,不过sem.h里有这个联合体的定义)

union semun

{

          int val;

          struct semid_ds *buf;

          unsigned short   *array;

};

 

 

 

cmd参数是指定对信号量进行什么操作。

 

IPC_RMID 删除信号量(对于删除信号量操作,一般可以不指定第四个参数了)。

SETVAL     通过设置union semun中的val成员来初始化,信号量的值。 这时sem_num参数的值表示的意思是第几个信号量。

GETVAL     获取第sem_num信号量的值,信号量的值是通过函数返回的(第四个参数可以不指定,即可以不写)。

SETALL      通过union semun中array所指的数组初始化有sem_num个信号量的信号量组。

IPC_STAT  IPC_SET  通过union semum里buf……获得或设置信号量属性信息。

 

semctl函数,不同的操作返回值是不一样的,但像设置、删除调用成功返回0,失败返回-1。

  • 信号量的 P V 操作

进程信号量的 PV操作时通过调用一个函数实现,具体是什么操作是由

结构体struct sembuf里的成员决定的。

 

 

struct sembuf

{

          short   sem_num;

          short   sem_op;

          short   sem_flg;

};

 

sem_num信号的编号,信号量组只有一个信号量时,它的总是0;

sem_op   1 表示 P 操作, -1 表示 V 操作。

sem_flg    通常被设置成SEM_UNDO……

 

参数num_sem_ops 是表示第二个参数sem_ops数组里元素的个数。

 

 

  • 信号量通信简单例子: