LInux进程间通信之信号量编程实例

一、信号量之创建信号量

#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>

int semget(key_t key,int nsems,int semflg);

   key:由ftok函数生成,唯一.

  nsems:需要申请的信号量数目.

  semflg:IPC_CREAT,不存在则创建,存在则返回以后的semid

     IPC_CREATE | IPC_EXCL 不存在则创建,存在则出错返回-1.

二、信号量之PV操作

#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>

int semop(int semid,struct sembuf *sops,size_t nsops);

  semid:信号量标识符

  sops:需要自定义的结构体(如下)

  nsops:每次处理多少个信号量

  sembuf 定义如下:

struct sembuf{
        unsigned short sem_num;    //除非使用一组信号量,否则它为0
        short          sem_op;       //信号量在操作时需要改变的数据,通常为-1(P)和+1(V)
        short          sem_flg;       //通常为SEM_UNDO,使得操作系统跟踪信号,在进程异常退出后,操作系统释放信号量
}

  (1)若sem_op为正,这对应于进程释放占用的资源数。sem_op值加到信号量的值上。(V操作)

  (2)若sem_op为负,这表示要获取该信号量控制的资源数。信号量值减去sem_op的绝对值。(P操作)

  (3)若sem_op为0,这表示调用进程希望等待到该信号量值变成0

   如果信号量值小于sem_op的绝对值(资源不能满足要求),则:

  (1)若指定了IPC_NOWAIT,则semop()出错返回EAGAIN.

  (2)若未指定IPC_NOWAIT,则信号量的semncnt值加1(因为调用进程将进入休眠状态),然后调用进程被挂起直至:

  ①此信号量变成大于或等于sem_op的绝对值;

  ②从系统中删除了此信号量,返回EIDRM;

  ③进程捕捉到一个信号,并从信号处理程序返回,返回EINTR.(与消息队列的阻塞处理方式很相似);

三、信号量的初始化

  semget并不初始化各个信号量的值,这个初始化必须通过以SETVAL命令(设置集合中的一个值)或SETALL命令(设置集合中的所有值)调用semctl来完成.

#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>

int semctl(int semid,int semnum,int cmd, ...);

  semid:信号量标识符

  senum:对信号量集的第几个信号量进行控制(从0开始)

  cmd:需要进行的操作.(共10种,初始化用到SETVAL)

  根据不同cmd,第四个参数联合体可能存在也可能不存在.(初始化需要用到该联合体)

  联合体声明如下:

typedef union semun{
        int val;                      //SETVAL的值
        struct semid_ds *buf;         //IPC_STAT ,IPC_SET的缓冲区 定义于<sys/sem.h>
        unsigned short *array;        //GETALL SETALL的数组
        struct seminfo *__buf;        //IPC_INFO的缓冲区
}semun;

四、信号量的删除

  删除也用到了semctl函数,cmd设置为IPC_RMID

posted @ 2017-06-12 14:26  Linux专题站  阅读(1045)  评论(0编辑  收藏  举报