Linux进程通信(System V)第四节------>信号量


1.并不是IPC机制,它是一种提供不同进程之间或者是同一个进程的不同的线程之间的同步!
2.类型:
 
     <1>.二元信号:值为0或者1,1说明有一个可以资源,0说明此时正好再用,其他进程等待
                  相当于是 P 和 V 问题...
                  
      <2>.计数信号量:值在0和一个大于0的值之间,一般是可用的资源数量
      
      <3>.计数信号量集:由一个或多个信号量组成的集合,每一个都是计数信号量。一般在25个以上。
      
      >>>:
         其使用就是我们知道的P/V操作一样,需要P是否有资源,如果P到,那么就是VALUE--,然后使用OK后还回来,也就是VALUE++,if申请不到资源就要阻塞自己!
 
3.信号量数据结构:
      
      #include<sys/sem.h>
      structsemid_ds                        //!> semaphore iddescription
      {
         structipc_perm      sem_perm;      //!> 操作权限结构体
         struct sem      *      sem_base;      //!> 设置信号量指针
         ushort               sem_nsems;      //!> 集合中信号量数量
         time_t               sem_otime;      //!> 最后一次(上一次)操作的时间
         time_t               sem_ctime;      //!> 上一次修改时间
      };
      
      #include<sys/ipc.h>
      structipc_perm                        //!> ipc permission( IPC 的权限设置结构体)
      {
         uid_t      uid;                     //!> 所有者用户ID
         gid_t      gid;                     //!> 所有者组ID
         uid_t      cuid;                     //!> 创建者ID
         gid_t      cgid;                     //!> 创建者组ID
         mode_t   mode;                     //!> 读写权限
         ulong_t   seq;                     //!> 槽的使用序列号
         key_t      key;                     //!> IPC KEY
      };
     
        mode 低九位:
                         0400   用户可读.
                         0200   用户可写.
 
                         0040   组成员可读.
                         0020   组成员可写.
 
                         0004   其他用户可读.
                         0002   其他用户可写.
      
      
      struct sem                                 //!> semapore
      {
         ushort_t      semval;                  //!> 信号值,非负
         short         sempid;                  //!> 上一次对其进行成功操作的进程PID
         ushort_t      semncnt;                  //!> 等待semval增加(长)的进程数
         ushort_t      semzcnt;                  //!>等待semval=0(为0)的进程数   
      }
      
      
      
4.信号量的创建和操作:
      
      <1>.semget函数用来创建一个信号量集合或者访问一个已经存在的!
      #include<sys/types.h>
      #include<sys/ipc.h>
      #include<sys/sem.h>
      
      int semget( key_t key, int nsems, int oflag);
      参数:
            nsems:信号量集合中的信号量个数(ATTENTION:if仅仅是访问一个EXIST的信号量集合,那么此值为0,因为一个信号量集合创建OK后,信号量数目不可改变! ) (但if是创建,那么肯定是一个大于0的数才是有意义的! )
            oflag:值是SEM_R和SEM_A的组合( 读与写),也可以是IPC_CREAT和IPC_EXCL的按位或                              
            
            返回值:信号量标志( semid )
            
            创建信号量OK后,对于semid_ds的初始化为:
                                                   sem_perm的uid和cuid为进程有效用户的ID,gid和cgid是进程有效用户的组ID
                                                   oflag:参数sem_perm.mode中
                                                   sem_otime = 0;
                                                   sem_ctime = 当前时间
                                                   sem_nsems = nsems;
                                                   
      <2>.创建OK后就可以使用semop对信号量进行操作。
      
      int semop( int semid, struct sembuf * opsptr,size_t nops );
      参数:
            struct sembuf
            {
               short      sem_num;            //!> 信号编号
               short      sem_op;            //!> 信号操作
               short      sem_flg;            //!> 操作标志
            };
      
            nops:由指针opsptr指向的数组中元素个数(数组反应内容:给所指定的某个特定的信号量指定一个操作!通过sem_num知道此特定信号量 )
         
      <3>.通过semctl函数对一个信号量进行各种操作:
      
      int semctl( int semid, int semnum, int cmd, ...);
      参数:
            semid:要进行操作的信号量集
            semnum:信号集中某个信号量( 0 ---> MAX - 1的取值 ),
                              可取为:GATVAL, SETVAL, GETNCNT, GETZCNT, GETPID
 
            最后一个参数可选,取决于第三个参数:cmd
            union semun
            {
               int                   val;            //!> 为了 SETVAL 使用
               structsemid_ds      buf;         //!>为了IPC_STAT使用   ( 用于取出值 )
               ushort         *      array;         //!> 为GETALL和SETALL使用
            };
            
            cmd 取值:
                     IPC_STAT:指定联合体是semid_ds,放在buf中
                     IPC_SET:按照buf中的数据设置此集合中的3个字段,即sem_perm结构体中的uid,gid,mode
                     IPC_RMID:从系统中删除该信号量集合
                     GETVAL:返回semnum的semval值
                     SETVAL:设置semnum的semval值,由semun中的val指定
                     GETPID:返回semnum的sempid值
                     GETNCNT:返回semnum的semncnt值
                     GETZCNT:返回semnum的semzcnt值
                     GETALL:取集合上所有的信号量放在array中
                     SEIALL:按照array中的值设置集合中的每个信号量的值
     
 
应用:信号量的使用是与“共享内存区”是连在一起的,所以在“进程通信的共享内存区中有具体的设计”
 
 
 
 
摘自 shanshanpt的专栏

相关内容

    暂无相关文章