Linux 进程通信(System V) 第四节------>信号量—转
1.并不是IPC机制,它是一种提供不同进程之间或者是同一个进程的不同的线程之间的同步!
2.类型:
相当于是 P 和 V 问题...
<2>.计数信号量:值在0和一个大于0的值之间,一般是可用的资源数量
<3>.计数信号量集:由一个或多个信号量组成的集合,每一个都是计数信号量。一般在25个以上。
>>>:
其使用就是我们知道的P/V操作一样,需要P是否有资源,如果P到,那么就是VALUE--,然后使用OK后还回来,也就是VALUE++,if申请不到资源就要阻塞自己!
3.信号量数据结构:
1 #include<sys/sem.h> 2 structsemid_ds //!> semaphore iddescription 3 { 4 structipc_perm sem_perm; //!> 操作权限结构体 5 struct sem * sem_base; //!> 设置信号量指针 6 ushort sem_nsems; //!> 集合中信号量数量 7 time_t sem_otime; //!> 最后一次(上一次)操作的时间 8 time_t sem_ctime; //!> 上一次修改时间 9 }; 10 11 #include<sys/ipc.h> 12 structipc_perm //!> ipc permission( IPC 的权限设置结构体) 13 { 14 uid_t uid; //!> 所有者用户ID 15 gid_t gid; //!> 所有者组ID 16 uid_t cuid; //!> 创建者ID 17 gid_t cgid; //!> 创建者组ID 18 mode_t mode; //!> 读写权限 19 ulong_t seq; //!> 槽的使用序列号 20 key_t key; //!> IPC KEY 21 }; 22 23 mode 低九位: 24 0400 用户可读. 25 0200 用户可写. 26 27 0040 组成员可读. 28 0020 组成员可写. 29 30 0004 其他用户可读. 31 0002 其他用户可写. 32 33 34 struct sem //!> semapore 35 { 36 ushort_t semval; //!> 信号值,非负 37 short sempid; //!> 上一次对其进行成功操作的进程PID 38 ushort_t semncnt; //!> 等待semval增加(长)的进程数 39 ushort_t semzcnt; //!>等待semval=0(为0)的进程数 40 }
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中的值设置集合中的每个信号量的值
应用:信号量的使用是与“共享内存区”是连在一起的,所以在“进程通信的共享内存区中有具体的设计”