System V 信号量机制
2016-07-10 23:53
417 查看
有三种 IPC我们称作XSI IPC,即消息队列、信号量以及共享存储器(共享内存),这就是我么所说的进程间通信的IPC,有了这些IPC提供给程序的通信接口,实现进程间的通信。
本文主要讨论的是信号量的机制。
semget()创建一个新的信号量集,或者存取一个已经存在的信号量集:
系统调用:semget();
原型:int semget(key_t key,int nsems,int semflg);
返回值:如果成功,则返回信号量集的IPC标识符。如果失败,则返回-1:errno=EACCESS(没有权限)
EEXIST(信号量集已经存在,无法创建)
EIDRM(信号量集已经删除)
ENOENT(信号量集不存在,同时没有使用IPC_CREAT)
ENOMEM(没有足够的内存创建新的信号量集)
ENOSPC(超出限制)
系统调用semget()的第一个参数是关键字值(一般是由系统调用ftok()返回的)。系统内核将此值和系统中存在的其他的信号量集的关键字值进行比 较。打开和存取操作与参数semflg中的内容相关。IPC_CREAT如果信号量集在系统内核中不存在,则创建信号量集。IPC_EXCL当和 IPC_CREAT一同使用时,如果信号量集已经存在,则调用失败。如果单独使用IPC_CREAT,则semget()要么返回新创建的信号量集的标识 符,要么返回系统中已经存在的同样的关键字值的信号量的标识符。如果IPC_EXCL和IPC_CREAT一同使用,则要么返回新创建的信号量集的标识
符,要么返回-1。IPC_EXCL单独使用没有意义。参数nsems指出了一个新的信号量集中应该创建的信号量的个数。
程序举例:
semop函数使用semget打开一个信号量集后,对其中一个或多个信号量的操作就使用semop(op--operate)函数来执行。
原型:int semop(int semid, struct sembuf *opsptr, size_t nops);
参数:semid:是semget返回的semid号。
nops:是数组opsptr的个数。
opsptr是操作结构的数组
struct sembuf
{
short sem_num; //信号量在semid集合中的序号:0到nsems - 1;
short sem_op; //操作
short sem_flag; //0, IPC_NOWAIT, SEM_UNDO
};
其中,sem_op值如下:
a、如果sem_op大于0,表示sem_num信号量所代表的资源的释放,semval += sem_op;
b、如果sem_op小于0,表示sem_num信号量所代表资源的分配,具体是:如果semval 大于等于 sem_op的绝对值,则semval -= sem_op绝对值;否则,阻塞知道条件满足
c、如果sem_op等于0,表示直到semval 等于0时才返回。
程序举例:
semctl函数用来直接控制信号量信息。
原型:int semctl(int semid, int semnum, int cmd, ../* union semun arg */);
其中semid是信号量集合,semnum是信号在集合中的序号,
union semun
{
int val; /* cmd == SETVAL */
struct semid_ds *buf /* cmd == IPC_SET或者 cmd == IPC_STAT */
ushort *array; /* cmd == SETALL, 或 cmd = GETALL */
};
cmd取值如下:
GETVAL, SETVAL : semid集合中semnum信号量当前的semval值
GETALL,SETALL :semid集合中所有信号量的值。
IPC_RMID:删除semid信号量集
GETPID:返回最后成功操作该信号的进程号。
IPC_STAT:返回semid集合中的struct semid_ds结构。
程序举例:
本文主要讨论的是信号量的机制。
semget()创建一个新的信号量集,或者存取一个已经存在的信号量集:
系统调用:semget();
原型:int semget(key_t key,int nsems,int semflg);
返回值:如果成功,则返回信号量集的IPC标识符。如果失败,则返回-1:errno=EACCESS(没有权限)
EEXIST(信号量集已经存在,无法创建)
EIDRM(信号量集已经删除)
ENOENT(信号量集不存在,同时没有使用IPC_CREAT)
ENOMEM(没有足够的内存创建新的信号量集)
ENOSPC(超出限制)
系统调用semget()的第一个参数是关键字值(一般是由系统调用ftok()返回的)。系统内核将此值和系统中存在的其他的信号量集的关键字值进行比 较。打开和存取操作与参数semflg中的内容相关。IPC_CREAT如果信号量集在系统内核中不存在,则创建信号量集。IPC_EXCL当和 IPC_CREAT一同使用时,如果信号量集已经存在,则调用失败。如果单独使用IPC_CREAT,则semget()要么返回新创建的信号量集的标识 符,要么返回系统中已经存在的同样的关键字值的信号量的标识符。如果IPC_EXCL和IPC_CREAT一同使用,则要么返回新创建的信号量集的标识
符,要么返回-1。IPC_EXCL单独使用没有意义。参数nsems指出了一个新的信号量集中应该创建的信号量的个数。
程序举例:
<span style="font-family:Microsoft YaHei;font-size:14px;">intopen_semaphore_set(key_t keyval,int numsems) { intsid; if(!numsems) return(-1); if((sid=semget(mykey,numsems,IPC_CREAT|0660))==-1) { return(-1); } return(sid); };</span>
semop函数使用semget打开一个信号量集后,对其中一个或多个信号量的操作就使用semop(op--operate)函数来执行。
原型:int semop(int semid, struct sembuf *opsptr, size_t nops);
参数:semid:是semget返回的semid号。
nops:是数组opsptr的个数。
opsptr是操作结构的数组
struct sembuf
{
short sem_num; //信号量在semid集合中的序号:0到nsems - 1;
short sem_op; //操作
short sem_flag; //0, IPC_NOWAIT, SEM_UNDO
};
其中,sem_op值如下:
a、如果sem_op大于0,表示sem_num信号量所代表的资源的释放,semval += sem_op;
b、如果sem_op小于0,表示sem_num信号量所代表资源的分配,具体是:如果semval 大于等于 sem_op的绝对值,则semval -= sem_op绝对值;否则,阻塞知道条件满足
c、如果sem_op等于0,表示直到semval 等于0时才返回。
程序举例:
<span style="font-family:Microsoft YaHei;font-size:14px;">static int op_sem(int sem_id, int op, int which)//信号量的操作举例 { struct sembuf sem; memset(&sem, '\0', sizeof(sem)); sem.sem_num = which; sem.sem_op = okp; sem.sem_flg = 0; return semop(sem_id, &sem, 1); }</span><pre name="code" class="cpp"><span style="font-family:Microsoft YaHei;">int sem_p(int sem_id, int which)//P操作 { int ret = op_sem(sem_id, -1, which); if(ret == 0){ printf("P operator is success!, errno code is : %d\n", errno); }else{ printf("P operator is failed!, errno code is : %d\n", errno); } return ret; } int sem_v(int sem_id, int which)//V操作 { int ret = op_sem(sem_id, 1, which); if(ret == 0){ printf("V operator is success!, errno code is : %d\n", errno); }else{ printf("V operator is failed!, errno code is : %d\n", errno); } return ret; }</span>
semctl函数用来直接控制信号量信息。
原型:int semctl(int semid, int semnum, int cmd, ../* union semun arg */);
其中semid是信号量集合,semnum是信号在集合中的序号,
union semun
{
int val; /* cmd == SETVAL */
struct semid_ds *buf /* cmd == IPC_SET或者 cmd == IPC_STAT */
ushort *array; /* cmd == SETALL, 或 cmd = GETALL */
};
cmd取值如下:
GETVAL, SETVAL : semid集合中semnum信号量当前的semval值
GETALL,SETALL :semid集合中所有信号量的值。
IPC_RMID:删除semid信号量集
GETPID:返回最后成功操作该信号的进程号。
IPC_STAT:返回semid集合中的struct semid_ds结构。
程序举例:
<span style="font-family:Microsoft YaHei;font-size:14px;">int destroy_sem(int sem_id)//使用semctl删除信号量 { int ret = semctl(sem_id, 0, IPC_RMID, NULL); if(ret == -1){ printf("destroy sem error\n"); return ret; } printf("destroy sem success, errno code is : %d\n", errno); return ret; }</span>
相关文章推荐
- 成为Java GC专家(3)—如何优化Java垃圾回收机制
- chrome使用技巧
- java面试宝典学习笔记(三)
- 自定义控件—Scroller屏幕平缓滑动工具类
- 谈谈Js闭包的那些事儿
- # android studio使用遇到的问题
- java内存划分
- 成为JavaGC专家(2)—如何监控Java垃圾回收机制
- Codeforces Round #360 (Div. 2) E. The Values You Can Make 01背包
- 自定义控件-继承ViewGrroup
- hiho #1082 : 然而沼跃鱼早就看穿了一切
- 成为JavaGC专家(1)—深入浅出Java垃圾回收机制
- Add Binary
- 爱奇艺Vip账号分享站
- BZOJ 2761 不重复数字(水题)
- 001——jdk环境配置
- redux异步操作学习笔记
- poj 3349 简单hash
- poj 1654 Area
- 一套完整的活动运营策划思路什么样子?