进程间通信——信号量
来源:互联网 发布:mysql服务占多大内存 编辑:程序博客网 时间:2024/06/03 20:26
信号量
信号量的作用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有。
信号量的值为正的时候,说明它空闲。所测试的线程可以锁定而使用它。若为0,说明它被占用,测试的线程要进入睡眠队列中,等待被唤醒。
信号量的作用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有。
信号量的值为正的时候,说明它空闲。所测试的线程可以锁定而使用它。若为0,说明它被占用,测试的线程要进入睡眠队列中,等待被唤醒。
为什么要使用信号量?
因为共享内存是可以由多个进程同时访问,假如有多个进程同时访问同一块地址的话,内存就会出错,或者是运算错误,所以当某个进程访问共享内存的时候,我们利用信号量去保护这片共享内存以防内存出错。
信号量的分类
在学习信号量之前,我们必须先知道——Linux提供两种信号量:
(1) 内核信号量,由内核控制路径使用
(2) 用户态进程使用的信号量,这种信号量又分为POSIX信号量和SYSTEMV信号量。POSIX信号量又分为有名信号量和无名信号量。
有名信号量,其值保存在文件中, 所以它可以用于线程也可以用于进程间的同步。
(1) 内核信号量,由内核控制路径使用
(2) 用户态进程使用的信号量,这种信号量又分为POSIX信号量和SYSTEMV信号量。POSIX信号量又分为有名信号量和无名信号量。
有名信号量,其值保存在文件中, 所以它可以用于线程也可以用于进程间的同步。
无名信号量,其值保存在内存中。
信号量的使用步骤
1.创建信号量---》semget
2.初始化信号量---》semctl
3.进行信号量的操作---》semop
1.创建信号量
头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
函数原型:
int semget(key_t key, int nsems, int semflg);
参数一:秘钥ftok()
参数二:需要创建信号量的个数 PS:(信号量是有个数的他从0下标开始)
参数三:权限
IPC_CREAT -》创建
IPC_EXCL -》检查
|0666 -》操作权限
返回值:信号量对象ID
失败返回:-1
2.初始化信号量
int semctl(int semid, int semnum, int cmd, ...);
参数一:要初始化的信号量对象ID
参数二:要初始化那个信号量
参数三:命令 GETVAL -》获取当前信号量的值(一般设备完毕后需要获取一下值,该值会放到返回值中)
SETVAL -》设置信号量的值 (该值应该填写到第4个参数中)
IPC_RMID -》删除信号量对象
参数四:通过命令来确定他的值
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
(Linux-specific) */
};
3.进行信号量的P\V操作
p -> 申请资源 V -> 释放资源
头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
函数原型:
int semop(int semid, struct sembuf *sops, unsigned nsops);
参数一:对象ID
参数二:操作结构体
struct sembuf
{
unsigned short sem_num; /* semaphore number */要操作哪一个信号量
short sem_op; /* semaphore operation */PV操作
P操作 填写 -1
V操作 填写 1
short sem_flg; /* operation flags */
IPC_NOWAIT 不阻塞
SEM_UNDO -》自动释放资源
0 -》默认操作
}
参数三:整形 -》 指定参照二的结构体数量 一般填写为1
-----------------------------------------------------------------------------------------
练习:使用信号量的pv操作
【sema.c】
#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <stdio.h>#include <stdlib.h>int main(){ //创建信号量对象 int semid=semget(ftok("/home/gec",400),2,IPC_CREAT|0666);if(semid == -1){perror("semid fail:"); exit(0);}else{ printf("crete ok\n");} //对信号量1进行初始化int ret=semctl(semid,0,SETVAL,1);if(ret == -1 ){ perror(" init sem:"); exit(0);}else{printf("init 1 ok %d\n",semctl(semid,0,GETVAL,NULL));}//对信号量2进行初始化 ret=semctl(semid,1,SETVAL,1);if(ret == -1 ){ perror(" init sem:"); exit(0);}else{printf("init 2 ok %d\n",semctl(semid,0,GETVAL,NULL));}//进行P-1 V+1操作 struct sembuf p; p.sem_num = 0; //要操作哪一个信号量 p.sem_op = -1; // -1为P操作 1为V操作 p.sem_flg = 0; //默认属性 struct sembuf v; v.sem_num = 0; v.sem_op = 1; v.sem_flg = 0; //进行PV操作2 struct sembuf p1; p1.sem_num = 1; //要操作哪一个信号量 p1.sem_op = -1; // -1为P操作 1为V操作 p1.sem_flg = 0; //默认属性 struct sembuf v1; v1.sem_num = 1; v1.sem_op = 1; v1.sem_flg = 0;int i=0; while(1) { //进行P操作 semop(semid,&p,1); printf("i=%d\n",i++); sleep(1); //进行V操作 semop(semid,&v1,1);}}
【semb.c】
#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <stdio.h>#include <stdlib.h>int main(){ //创建信号量对象 int semid=semget(ftok("/home/gec",400),2,IPC_CREAT|0666);if(semid == -1){perror("semid fail:");exit(0);}else{ printf("crete ok\n");}//进行P-1 V+1操作 struct sembuf p; p.sem_num = 0; //要操作哪一个信号量 p.sem_op = -1; // -1为P操作 1为V操作 p.sem_flg = 0; //默认属性 struct sembuf v; v.sem_num = 0;v.sem_op = 1;v.sem_flg = 0; //进行PV操作2 struct sembuf p1; p1.sem_num = 1; //要操作哪一个信号量 p1.sem_op = -1; // -1为P操作 1为V操作 p1.sem_flg = 0; //默认属性 struct sembuf v1; v1.sem_num = 1; v1.sem_op = 1; v1.sem_flg = 0; int i=0; while(1) { //进行P操作 semop(semid,&p1,1); printf("i=%d\n",i++); sleep(1); //进行V操作 semop(semid,&v,1);}}
运行程序sema.c,初始化信号量1,2,运行semb.c后,两个进程的变量i每隔1s加1.
阅读全文
0 0
- 进程间通信—信号量
- 进程间通信—信号量
- Linux进程间通信——信号量
- Linux进程间通信——信号量
- Linux进程间通信——信号量
- 进程间通信IPC——信号量
- Linux进程间通信——信号量
- Linux进程间通信——信号量
- 进程间通信——信号量
- 进程间通信——信号量
- 进程间通信——信号量
- Linux进程间通信——信号量
- 进程间通信——信号量
- 进程间通信——信号量
- 进程间通信——信号量
- Linux进程间通信——信号量
- 进程间通信之——信号量
- Linux进程间通信—使用信号量
- CNTK API文档翻译(14)——实验图像识别
- 浅谈JS中正则表达式(RegExp)的使用
- bzoj1677 [Usaco2005 Jan]Sumsets 求和(递推)
- 内存泄露从入门到精通三部曲之基础知识篇
- Linux内核中Netfilter架构介绍
- 进程间通信——信号量
- iOS Swift print了解和不换行
- TCP流量控制与拥塞控制浅析
- JQuery实现 任务清单案例
- PAT基础题 4-1 简单输出整数
- LeetCode18--4Sum--数组中某四个元素之和为某个输入的数值,输出这四个元素的值,并且这个四元组唯一
- mfc中设置statictext的字体和颜色
- linux-磁盘的管理
- try-with-resource小demo遇到的一些小问题