【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 ...
随机推荐
- toolbar menu 字体颜色和大小
Toolbar菜单中menu当中我们大多数都使用图片来按钮,可是有些时候我们也会直接使用文字,文字的颜色如何修改呢. 其实很简单,我们只要修改styles.xml文件中,添加一句 <item n ...
- Spark Streaming实例
Spark Streaming实例分析 2015-02-02 21:00 4343人阅读 评论(0) 收藏 举报 分类: spark(11) 转载地址:http://www.aboutyun.co ...
- python学习笔记十:异常
一.语法 #!/usr/bin/python filename='hello' #try except finally demo try: open('abc.txt') print hello ex ...
- mac虚拟机上(centos系统)设置联网
前面介绍了mac安装虚拟机VirtualBox,并在虚拟机上装上了centos,这里在说明一下联网问题. 首先打开centos系统,并输入命令$ ip addr 可得到如下: 发现找不到ip地址,这时 ...
- 孤荷凌寒自学python第十九天python函数嵌套与将函数作为返回对象及闭包与递归
孤荷凌寒自学python第十九天python函数嵌套与将函数作为返回对象及闭包与递归 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) Python函数非常的灵活,今天学习了python函数的以 ...
- shell之netstat命令
语 法:netstat [-acCeFghilMnNoprstuvVwx] [-A<网络类型>][--ip] 补充说明:利用netstat指令可让你得知整个Linux系统的网络情况. ...
- css深入理解vertical-align
第一讲:vertical-align家族基本认识 了解vertical-align支持的属性值以及组成 属性: 1.inherit 2.线类 baseline,top,middle,bottom 3. ...
- 蓝桥杯_风险度量_dfs_无向图两节点间的所有路径
标题:风险度量 X星系的的防卫体系包含 n 个空间站.这 n 个空间站间有 m 条通信链路,构成通信网.两个空间站间可能直接通信,也可能通过其它空间站中转. 对于两个站点x和y (x != y), 如 ...
- 第二阶段团队冲刺-three
昨天: 修复博客作业查询功能. 今天: 绘制logo. 遇到的问题: 无.
- HashMap 的深入学习
Java为数据结构中的映射定义了一个接口java.util.Map,此接口主要有四个常用的实现类,分别是HashMap.Hashtable.LinkedHashMap和TreeMap,类继承关系如下图 ...