进程间通讯:信号量
来源:互联网 发布:淘宝商家从哪里进货 编辑:程序博客网 时间:2024/06/06 00:59
一、与信号量有关的几个知识点
临界资源:同一时刻,只能被一个进程访问的资源 临界区:访问临界资源的代码区 原子操作:任何情况下都不能被打断的操作 内核对象:对通讯值的记录,类似管道
二、信号量的实质和作用
信号量的实质是记录资源同时能被多少个进程访问,作用于进程间的同步控制,不同于锁,它可以有N个有限值。
举个例子,信号量类似一个停车场,而锁类似停车场中的一个停车位,当车辆进入停车场时,停车位数量减一,但是在有其它空余停车位时,车辆依然可以进入停车场。而一个停车位有车辆时,其它车辆不可以进入这个停车位。
总的来说,信号量的通讯信息是资源的可访问数量,不同于管道的数据。
三、信号量的操作
1. 创建或获取:Int semget((key_t)key, int nsems, int flag);
Key是键值,是一个唯一的非零整数,类似于一个“身份证号”,其它进程通过这个“身份证号”来使用这组信号量;Nsems 用来确定内核创建的信号量数组大小;Flag 用来确定操作和权限,可以通过与上PC_CREAT在不存在该信号量时创建,存在时获取;返回值:非零的信号量标识符,其它函数根据信号量标识符来操作,而非键值;
栗子:int sem_id = semget( (key_t)1234, 1, 0666|IPC_CREAT );
2. P/V操作:int semop( int semid , struct sembuf * buf , int lenth);
Semid: semget返回的信号量标识符struct sembuf * buf:一个结构体 struct sembuf { Short sem_num;//除非使用一组信号量,否则它为0 short sem_op;//信号量在一次操作中需要改变的数据,通常是两个数, 一个是-1,即P(等待)操作,//一个是+1,即V(发送信号)操作。 shortsem_flg;//通常为SEM_UNDO,使操作系统跟踪信号 };
3. 初始化和删除:int semctl(int sem_id, int sem_num, int command, uniousemun);
Semid: semget返回的信号量标识符 sem_num:信号量数组的下标,如果只有一个元素,则为零command:操作,SETVAL为初始化,IPC_RMID为删除uniou semun:在初始化时,需要用到 unionsemun { int val; //初始化资源的个数 struct semid_ds *buf; unsigned short *arry; };
四、通过一个简单实例来掌握信号量,进程A负责读取键盘输入,直到读取“OK”,进程B打印出100以内的素数。
需要注意的是,在多个进程之间使用信号量通讯,可以将P操作之后的代码认为是临界区,即P操作不是简单的减一,而是要理解为:
如果能做P操作之后临界区的事件,那么减一,否则等待
sem.h 为头文件
sem.c 将信号量操作进行了简单的封装
maina.c和mainb.c是一个简单的示例:
maina读取键盘输入,直到输入OK,mainb打印100以内的素数
sem.h:
#ifndef _SEM_H#define _SEM_H#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <assert.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>int semid;union semun{ int val; //struct semid_ds *buf; //unsigned short * arry;};void sem_get(int key,int len,int val);void sem_p();void sem_v();void sem_del();#endif
sem.c:
#include "sem.h"void sem_get(int key,int len,int val){ semid = semget((key_t)key,len,0666); if(semid == -1) { semid = semget((key_t)key,len,0666|IPC_CREAT); assert(semid != -1); union semun v; v.val = val; if(semctl(semid,0,SETVAL,v)==-1) { perror("error"); exit(0); } }}void sem_p(){ struct sembuf sem; sem.sem_num = 0; sem.sem_op = -1; sem.sem_flg = SEM_UNDO; if(semop(semid, &sem, 1)==-1) { perror("perror"); exit(0); }}void sem_v(){ struct sembuf sem; sem.sem_num = 0; sem.sem_op = 1; sem.sem_flg = SEM_UNDO; if(semop(semid, &sem, 1)==-1) { perror("perror"); exit(0); }}void sem_del(){ if(semctl(semid,0,IPC_RMID)==-1) { perror("delperror"); exit(0); }}
进程A:
#include "sem.h"int main(){ sem_get(111,1,0); while(1) { char buff[128]={0}; fgets(buff,127,stdin); if(strncmp(buff,"ok",2)==0) { sem_v(); break; } } sem_del(); return 0;}
进程B:
#include "sem.h"void prime(){ int i,j; for(i=2;i<=100;i++) { for(j=2;j<=i-1;j++) { if(i%j==0) break; } if(j>=i) printf("%d\n",i); }}int main(){ sem_get(111,1,0); sem_p(); prime(); return 0;}
阅读全文
1 0
- 进程间通讯:信号量
- 进程间通讯--信号量
- linux 进程间通讯--信号量
- Linux进程间通讯之信号量
- Linux进程间通讯之信号量sem
- 进程间通讯之信号量(实例)
- 进程间通讯---信号量练习(二)
- 进程间通讯(二)信号量
- 进程间通讯——信号量
- 进程间通讯——信号量
- 进程间通讯——信号量
- Linux—进程间通讯—信号量
- 进程间的通讯方式_信号量
- 进程通讯-信号量
- Linux进程间通讯四--信号量通讯机制
- linux进程通讯之信号量
- Linux中进程通讯--信号量
- linux进程间通讯-System V IPC 信号量
- MySQL表增删改查
- 跳出工作的死循环
- 集合学习--TreeMap 源码初探
- hihocoder 1078 : 线段树的区间修改
- ANDROID样式的开发:SELECTOR篇
- 进程间通讯:信号量
- 认真分析mmap:是什么 为什么 怎么用
- Swift 集成 NIMSDK 踩坑之路
- 故障处理总结
- yii2 数字以千分位格式显示
- QT5每日一学(五)QT布局管理器
- 存储过程
- Single Number解题思路
- Nginx总结