【linux高级程序设计】(第十一章)System V进程间通信 3
信号量通信机制

可以看到,跟消息队列类似,也是包括两个结构。
int semget (key_t __key, int __nsems, int __semflg) : 创建信号量集合
第一个参数:ftok产生的key值
第二个参数:创建的信号量个数
第三个参数:权限信息
创建信号量例子:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<sys/types.h> int main(int argc, char * argv[])
{
int sem;
key_t key;
if((key = ftok(".",'B'))==-)
{
perror("ftok");
exit(EXIT_FAILURE);
}
if((sem = semget(key, , IPC_CREAT|)) == -)
{
perror("semget");
exit(EXIT_FAILURE);
}
printf("sem1 id is: %d\n", sem);
semctl(sem, , IPC_RMID, (struct msquid_ds*)); //删除信号量集合
return ;
}
int semctl (int __semid, int __semnum, int __cmd, ...) :控制信号量集合、信号量
第一个参数:要操作的信号量集合标识
第二个参数:信号量编号。如果操作整个信号量集合无意义;如果是某个信号量,为信号量下标。
第三个参数:执行的操作。 如果对整个集合操作,则包括:IPC_RMID, IPC_SET, IPC_STAT, IPC_INFO
如果是对某个或某些信号量操作,则包括GETPID、GETVAL、GETALL、GETNCNT、GETZCNT、SETVAL、SETALL.具体见图

设置读取信号量的例子
#include<stdio.h>
#include<sys/types.h>
#include<sys/sem.h>
#include<errno.h>
#define MAX_SEMAPHORES 5
int main(int argc, char *argv[])
{
int i, ret, semid;
unsigned short sem_array[MAX_SEMAPHORES];
unsigned short sem_read_array[MAX_SEMAPHORES];
union senmun
{
int val;
struct semid_ds *buf;
unsigned short *array;
}arg;
//创建信号量集合
semid = semget(IPC_PRIVATE, MAX_SEMAPHORES, IPC_CREAT|);
if(semid != -)
{
//初始化
for(i = ; i < MAX_SEMAPHORES; i++)
sem_array[i] = (unsigned short)(i + );
arg.array = sem_array;
//设置所有信号量的值
ret = semctl(semid, , SETALL, arg);
if(ret == -)
printf("SETALL failed (%d)\n", errno); arg.array = sem_read_array;
//获取所有信号量的值
ret = semctl(semid, , GETALL, arg); //获取所有信号量的值
if(ret == -)
printf("GETALL failed (%d)\n", errno); for(i = ; i < MAX_SEMAPHORES; i++)
printf("Semaphore %d, value %d\n", i, sem_read_array[i]); //逐次获取信号量值
for(i = ; i < MAX_SEMAPHORES; i++)
{
ret = semctl(semid, i, GETVAL);
printf("Semaphore %d, value %d\n", i, sem_read_array[i]);
}
//删除信号量集合
ret = semctl(semid, , IPC_RMID);
}
else
{
printf("Could not allocate semaphore (%d)\n", errno);
}
return ;
}

int semop (int __semid, struct sembuf *__sops, size_t __nsops) :操作信号量
第一个参数:要操作的信号量集合ID
第二个参数
struct sembug{
unsigned short sem_num;
short sem_op;
short sem_flg;
};
- sem_num:操作的信号量编号
- sem_op:用于信号量的操作,正数表示增加信号量的值;负数表示减小信号量的值;0表示测试当前值是否为0
- sem_flg:操作标识,IPC_NOWAIT,如果等待立即返回;SEM_UNDO,当进程退出后,该进程对sem进行的操作将被撤销。
下面的代码,对信号量1做P操作(get),对信号量2做V操作(release)
struct sembuf sops[];
sops[].sem_num = ;
sops[].sem_op = -;
sops[].sem_flg = ; sops[].sem_num = ;
sops[].sem_op = ;
sops[].sem_flg = ; semop(mysemid, sops, )
信号量解决生产者消费者问题,设有100个空位的缓冲池。
下面代码,经验证可用。
生产者代码:
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<errno.h>
int sem_id;
void init()
{
key_t key;
int ret;
unsigned short sem_array[];
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
}arg;
key = ftok(".",'s');
sem_id = semget(key, , IPC_CREAT|);
sem_array[] = ; //0号下标 生产者
sem_array[] = ;
arg.array = sem_array;
ret = semctl(sem_id, , SETALL, arg); //初始化
if(ret == -)
printf("SETALL failed (%d)\n", errno);
printf("productor init is %d\n", semctl(sem_id, , GETVAL));
printf("space init is %d\n\n", semctl(sem_id, , GETVAL));
}
void del()
{
semctl(sem_id, , IPC_RMID);
}
int main(int argc, char *argv[])
{
struct sembuf sops[]; sops[].sem_num = ;
sops[].sem_op = ; //生产者数量加一
sops[].sem_flg = ; sops[].sem_num = ;
sops[].sem_op = -; //消费者数量减一
sops[].sem_flg = ; init();
printf("this is productor\n");
while()
{
printf("\n\nbefore produce:\n");
printf("productor number is %d\n", semctl(sem_id, , GETVAL));
printf("space init is %d\n\n", semctl(sem_id, , GETVAL));
semop(sem_id, (struct sembuf *)&sops[], ); //先预定一个空位
printf("now producing.....\n");
semop(sem_id,(struct sembuf *)&sops[], ); //生产出一个产品 释放一个产品
printf("\nafter produce:\n");
printf("productor number is %d\n", semctl(sem_id, , GETVAL));
printf("space number is %d\n", semctl(sem_id, , GETVAL));
sleep();
}
del();
}
消费者代码:
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<errno.h>
int sem_id;
void init()
{
key_t key;
key = ftok(".", 's');
sem_id = semget(key, , IPC_CREAT|);
}
int main(int argc, char *argv[])
{
init();
struct sembuf sops[]; sops[].sem_num = ;
sops[].sem_op = -; //产品数量减一
sops[].sem_flg = ; sops[].sem_num = ;
sops[].sem_op = ; //空位数量加一
sops[].sem_flg = ;
printf("this is customer\n"); while()
{
printf("\n\nbefore consume:\n");
printf("productor is %d\n", semctl(sem_id, , GETVAL));
printf("space is %d\n", semctl(sem_id, , GETVAL));
semop(sem_id, (struct sembuf *)&sops[], ); //预定一个要消费的产品
printf("now consuming.....\n");
semop(sem_id,(struct sembuf *)&sops[], ); //增加一个空位
printf("\nafter consume:\n");
printf("productor is %d\n", semctl(sem_id, , GETVAL));
printf("space is %d\n", semctl(sem_id, , GETVAL));
sleep();
}
}
【linux高级程序设计】(第十一章)System V进程间通信 3的更多相关文章
- 第三十一章 System V信号量(二)
用信号量实现进程互斥示例 #include <unistd.h> #include <sys/types.h> #include <stdlib.h> #inclu ...
- 读书笔记 - js高级程序设计 - 第十一章 DOM扩展
对DOM的两个主要的扩展 Selectors API HTML5 Element Traversal 元素遍历规范 querySelector var body = document.query ...
- 《JavaScript高级程序设计》——第二章在HTML使用JavaScript
这章讲的是JavaScript在HTML中的使用,也就是<script>元素的属性.书中详细讲了async.defer.src和type四个<script>的属性. 下面是对第 ...
- ipc - System V 进程间通信机制
SYNOPSIS 总览 # include <sys/types.h> # include <sys/ipc.h> # include <sys/msg.h> # ...
- 【linux高级程序设计】(第十一章)System V进程间通信 1
System V, 曾经也被称为 AT&T System V,是Unix操作系统众多版本中的一支. 传统上,System V 被看作是两种UNIX"风味"之一(另一个是 B ...
- Linux进程通信 之 信号灯(semphore)(System V && POSIX)
一. 信号灯简介 信号灯与其他进程间通信方式不大相同,它主要提供对进程间共享资源访问控制机制. 相当于内存中的标志,进程可以根据它判定是否能够访问某些共享资源,同时,进程 也可以修改该标志.除了用于访 ...
- 《Unix网络编程》卷2 读书笔记 第3章- System V IPC
1. 概述 三种类型的System V IPC:System V 消息队列.System V 信号量.System V 共享内存区 System V IPC在访问它们的函数和内核为它们维护的信息上共享 ...
- 第11章 System V 信号量
11.1 概述 信号量按功能分:二值信号量.计数信号量.信号量集:其中二值信号量和计数信号量指的是Posix信号量,信号量集指的是System V信号量.
- 第6章 System V消息队列
6.1 概述 System V消息队列在内核中是list存放的,头结点中有2个指针msg_first 和msg_last.其中每个节点包含:下个节点地址的指针.类型.长度.数据等. 6.2 函数 6. ...
- 第3章 System V IPC
3.1 概述 System V IPC 包含:System V消息队列.System V信号量.System V共享内存. 3.2 key_t 键和 ftok函数 这三种类型的System V IPC ...
随机推荐
- webstorm git提交不成功的
git pull git pull origin master git pull origin master --allow-unrelated-histories
- laravel5.5入口文件分析
入口文件 public/index.php 1.加载composer的自动加载器 require __DIR__.'/../vendor/autoload.php'; 自动加载,不用再各种requir ...
- PaaS服务之路漫谈(一)
此文已由作者尧飘海授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. PaaS服务之路漫谈(一) 1983年,SUN公司提出的网络即计算的理念:2006年亚马逊(Amazon)推 ...
- 在sqlserver 中如何导出数据库表结构到excel表格中
先建空白excel--在数据库中的左侧找到该表, 选中需要导出的数据--Ctrl+C复制--打开记事本修改编码格式为Unicode-不自动换行保存--Ctrl+A--Ctrl+C,再打开excel-- ...
- DOS程序员手册(十三)
744页 在DPMI 1.0下,系统会修改并重新装载所有含选择符的段寄存器,并且将所有 含有要释放的选择符的寄存器清空为0. 客户程序绝不能修改或释放该功能分配的任何描述符.Int 31h.功能010 ...
- 油田(DFS)
//DFS:油田问题 #include <iostream> using namespace std; ][]; int n,m; //一个网格的8个方向 ][] = {{-,-},{-, ...
- jmeter学习(二),如何安装jmeter?
官网地址:http://jmeter.apache.org/download_jmeter.cgi 如下图数字3.2表示的是版本号,jmeter是基于java的压力测试工具.所以运行环境一定要满足最低 ...
- 孤荷凌寒自学python第五十三天使用python写入和修改Firebase数据库中记录
孤荷凌寒自学python第五十三天使用python写入和修改Firebase数据库中记录 (完整学习过程屏幕记录视频地址在文末) 今天继续研究Firebase数据库,利用google免费提供的这个数 ...
- (转)KlayGE游戏引擎 :高效的GBUFFER管理方式
转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=3304 个顶点.这样的数据对GPU来说是很头疼的.所以引擎往往需要在Buffer上做一些工作来 ...
- centos6 install cobbler
cobbler 安装 一:定义yum源 wget -c -O CentOS-Base.repo http://mirrors.163.com/.help/CentOS6-Base-163.repo ...