linux进程间通信——深入理解linux信号量( 二 )


2、信号灯值操作 linux可以增加或减小信号灯的值,相应于对共享资源的释放和占有 。具体参见后面的semop系统调用 。
3、获得或设置信号灯属性: 系统中的每一个信号灯集都对应一个struct sem_array结构,该结构记录了信号灯集的各种信息,存在于系统空间 。为了设置、获得该信号灯集的各种信息及属性,在用户空间有一个重要的联合结构与之对应,即union semun 。

linux进程间通信——深入理解linux信号量

文章插图
 
联合semun数据结构:
union semun{int val; /* value for SETVAL */struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */unsigned short *array; /* array for GETALL & SETALL */struct seminfo *__buf; /* buffer for IPC_INFO */ //test!!void *__pad;};The semid_ds data structure is defined in <sys/sem.h> as follows: struct semid_ds {struct ipc_perm sem_perm;/* Ownership and permissions */time_tsem_otime; /* Last semop time */time_tsem_ctime; /* Last change time */unsigned shortsem_nsems; /* No. of semaphores in set */}; The ipc_perm structure is defined in <sys/ipc.h> as follows (the highlighted fields are settable using IPC_SET):struct ipc_perm {key_t key;/* Key supplied to semget() */uid_t uid;/* Effective UID of owner */gid_t gid;/* Effective GID of owner */uid_t cuid;/* Effective UID of creator */gid_t cgid;/* Effective GID of creator */unsigned short mode;/* Permissions */unsigned short seq;/* Sequence number */}; seminfo, defined in <sys/sem.h> if the _GNU_SOURCE feature test macro is defined: structseminfo {int semmap;/* #(number?) of entries in semaphore map;unused */int semmni;/* Max. # of semaphore sets */int semmns;/* Max. # of semaphores in allsemaphore sets */int semmnu;/* System-wide max. # of undostructures; unused */int semmsl;/* Max. # of semaphores in a set */int semopm;/* Max. # of operations for semop() */int semume;/* Max. # of undo entries perprocess; unused */int semusz;/* size of struct sem_undo */int semvmx;/* Maximum semaphore value */int semaem;/* Max. value that can be recorded forsemaphore adjustment (SEM_UNDO) */};The semmsl, semmns, semopm, and semmni settings can be changed via /proc/sys/kernel/sem; see proc(5) for details.
信号灯API
1、文件名到键值#include <sys/types.h>#include <sys/ipc.h>key_t ftok (char*pathname, char proj);它返回与路径pathname相对应的一个键值,具体用法请参考《Linux环境进程间通信(三):消息队列》 。
2、 linux特有的ipc()调用:int ipc(unsigned int call, int first, intsecond, int third, void *ptr, long fifth);
参数call取不同值时,对应信号灯的三个系统调用: 当call为SEMOP时,对应int semop(int semid, struct sembuf *sops, unsigned nsops)调用; 当call为SEMGET时,对应int semget(key_t key, int nsems,int semflg)调用; 当call为SEMCTL时,对应int semctl(int semid,int semnum,int cmd,union semun arg)调用; 这些调用将在后面阐述 。
注:本人不主张采用系统调用ipc(),而更倾向于采用系统V或者POSIX进程间通信API 。原因已在Linux环境进程间通信(三):消息队列中给出 。
3、系统V信号灯API系统V消息队列API只有三个,使用时需要包括几个头文件:
#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>1)int semget(key_t key, int nsems, int semflg) 参数key是一个键值,由ftok获得,唯一标识一个信号灯集,用法与msgget()中的key相同;参数nsems指定打开或者新创建的信号灯集中将包含信号灯的数目;semflg参数是一些标志位 。参数key和semflg的取值,以及何时打开已有信号灯集或者创建一个新的信号灯集与msgget()中的对应部分相同 。该调用返回与健值key相对应的信号灯集描述字 。调用返回:成功返回信号灯集描述字,否则返回-1 。注:如果key所代表的信号灯已经存在,且semflg指定了IPC_CREAT|IPC_EXCL标志,那么即使参数nsems与原来信号灯的数目不等,返回的也是EEXIST错误;如果semflg只指定了IPC_CREAT标志,那么参数nsems必须与原来的值一致,在后面程序实例中还要进一步说明 。
Upon creation, the least significant 9 bits of the argument semflg define the permissions (for owner, group and others) for the semaphore set. These bits have the same format, and the same meaning, as the mode argument of open(2) (though the execute permissions are not meaningful for semaphores, and write permissions mean permission to alter semaphore values)
例如:IPC_CREAT | 权限标识
2)int semop(int semid, struct sembuf *sops, unsigned nsops); semid是信号灯集ID,sops指向数组的每一个sembuf结构都刻画一个在特定信号灯上的操作 。nsops为sops指向数组的大小 。sembuf结构如下:
struct sembuf{unsigned short sem_num; /* semaphore index in array */short sem_op; /* semaphore operation */short sem_flg; /* operation flags */};


推荐阅读