Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2123964
  • 博文数量: 229
  • 博客积分: 7217
  • 博客等级: 上校
  • 技术积分: 3224
  • 用 户 组: 普通用户
  • 注册时间: 2009-02-19 17:23
个人简介

个人主页https://xugaoxiang.com,微信公众号: Dev_Club 或者搜索 程序员Club

文章分类

全部博文(229)

文章存档

2017年(1)

2016年(20)

2015年(23)

2013年(1)

2012年(23)

2011年(68)

2010年(62)

2009年(31)

分类: LINUX

2012-07-01 22:03:56

说到底,信号量就是用来控制多个进程对共享资源使用的一个计数器

相关数据结构
1、sem
    信号量对象是多个信号量的集合,而这个集合在linux中是以数组的形式实现的,数组的每个成员都是一个单独的信号量,即sem结构

点击(此处)折叠或打开

  1. struct
  2. {
  3.     short sempid;   /*最近一次操作信号量的进程的id*/
  4.     unsigned short semval;  /*信号量的计数值*/
  5.     unsigned short semncnt; /*等待使用资源的进程数目*/
  6.     unsigned short semzcnt; /*等待资源完全空闲的进程数目*/
  7. }
   
2、semun

点击(此处)折叠或打开

  1. union semun 
  2. {
  3.     int val;            /* value for SETVAL */
  4.     struct semid_ds *buf;    /* buffer for IPC_STAT & IPC_SET */
  5.     unsigned short *array;    /* array for GETALL & SETALL */
  6.     struct seminfo *__buf;    /* buffer for IPC_INFO */
  7.     void *__pad;
  8. };
   
3、sembuf
    被用来定义对信号量对象的基本操作。

点击(此处)折叠或打开

  1. struct sembuf
  2. {
  3.     unsigned short sem_num;     /* 接受操作的信号量在信号量数组中的序号,即数组下标 */
  4.     short        sem_op;        /* 定义了进行的操作,取值正、0和负值 */
  5.     short        sem_flg;       /* 控制操作行为的标志 */
  6. };
    3.1 如果sem_op值为负,就从指定的信号量中减去相应的值,对应着获取信号量所监控的资源的操作。若sem_flg中没有指定IPC_NOWAIT标志,如果现有的信号量数值小于sem_op的绝对值(表示现有资源少于所需资源),调用semop()的进程就会阻塞直到信号量的数值大于sem_op的绝对值(表示有足够的资源)。
    3.2 如果sem_op值为正,就在指定的信号量中加上相应的值,这对应着释放信号量所监控的资源的操作。
    3.3 如果sem_op值为零,调用semop()的进程会被阻塞直到对应的信号量值为0。这操作就是等待信号量所监控的资源被全部使用。利用这个操作可以动态监控资源的使用并调整资源的分配,避免不必要的等待。

4、semid_ds

点击(此处)折叠或打开

  1. struct semid_ds
  2. {
  3.     struct ipc_perm    sem_perm;        /* permissions .. see ipc.h */
  4.     __kernel_time_t    sem_otime;        /* 最近一次semop操作的时间 */
  5.     __kernel_time_t    sem_ctime;        /* 信号量对象最近一次改动发生的时间 */
  6.     struct sem    *sem_base;        /* 信号里数组的起始地址 */
  7.     struct sem_queue *sem_pending;        /* 指向还未进行的操作 */
  8.     struct sem_queue **sem_pending_last;    /* 指向最后一个还未进行的操作 */
  9.     struct sem_undo    *undo;            /* undo requests on this array */
  10.     unsigned short    sem_nsems;        /* 信号量数组成员数目 */
  11. };
    和msqid_ds类似,semid_ds用来储存每个信号量对象的有关信息。


相关函数
1、semget()

点击(此处)折叠或打开

  1. #include <sys/types.h>
  2. #include <sys/ipc.h>
  3. #include <sys/sem.h>

  4. int semget(key_t key, int nsems, int semflg);
    semget建立新的信号量对象或者获取已有对象的标识符。参数semflg与消息队列中的msgflg参数取值一样,详见http://blog.chinaunix.net/uid-12845622-id-3258301.html;参数nsems是信息量对象中信号量的数目,也就是信号量数组成员的个数。/usr/include/linux/sem.h中定义了它的上限,#define SEMMSL  250
   
2、semop()

点击(此处)折叠或打开

  1. #include <sys/types.h>
  2. #include <sys/ipc.h>
  3. #include <sys/sem.h>

  4. int semop(int semid, struct sembuf *sops, unsigned nsops);
    semop()用来改变信号量对象中各个信号量的状态。参数sops是sembuf类型的数组,定义了semop()函数所要进行的操作序列;参数nsops是sops数组的长度也就是semop()进行的操作个数。

3、semctl()

点击(此处)折叠或打开

  1. #include <sys/types.h>
  2. #include <sys/ipc.h>
  3. #include <sys/sem.h>

  4. int semctl(int semid, int semnum, int cmd, ...);
    semctl()直接来控制信号量对象。semid为信号量对象标识符,semnum信号量在集合中的序号。根据cmd的取值,可带第4个参数,union semun arg。cmd可取如下值
    IPC_STAT: 取得semid的semid_ds信息,并存放在arg的buf中
    IPC_SET : 用arg中的buf设定信号量对象的semid_ds结构
    IPC_RMID: 删除信号量对象
    GETALL    : 取得信号量对象所有信号量的值,并存放在arg的array中返回
    GETNCNT : 返回正在等待使用某个信号量所控制的资源的进程数目
    GETPID    : 返回最近一个对某个信号量调用semop()的进程的pid
    GETVAL    : 返回集合中最后一个信号量的semval值
    GETZCNT : 返回正在等待某个信号量所控制资源被全部使用的进程数目
    SETALL   :用arg中array来设定对象内处个信号量的值
    SETVAL    : 用arg中val的值来设定对象中某个信号量的值  




阅读(2252) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~