Linux 进程间通信 信号灯集
1.特点: 信号灯集,是控制访问临界资源
信号灯(semaphore),也叫信号量。它是不同进程间或一个给定进程内部不同线程间同步的机制System V的信号灯是一个或者多个信号灯的一个集合(允许对集合中的多个计数信号灯进行同时操作)。其中的每一个都是单独的计数信号灯。而Posix信号灯指的是单个计数信号灯
2.信号灯种类:
posix有名信号灯
posix基于内存的信号灯(无名信号灯)(线程)
System V信号灯(IPC对象)(信号灯的值就是代表资源的数量)
3.创建步骤:
1)产生key值
2)创建信号灯集
3)初始化信号灯(对信号灯集中的每个信号灯进行初始化)
4)信号灯的P-V操作
5)删除信号灯集
4.相关函数:
1)int semget(key_t key, int nsems, int semflg);
功能:创建/打开信号灯
参数:key:ftok产生的key值(和信号灯关联的key值)
nsems:信号灯集中包含的信号灯数目
semflg:信号灯集的访问权限,通常为IPC_CREAT |0666
返回值:成功:信号灯集ID ; 失败:-1
2)int semop ( int semid, struct sembuf *opsptr, size_t nops);
功能:对信号灯集合中的信号量进行P - V操作
参数:semid:信号灯集ID
struct sembuf {
short sem_num; // 要操作的信号灯的编号
short sem_op; // 0 : 等待,直到信号灯的值变成0 // 1 : 释放资源,V操作 // -1 : 分配资源,P操作
short sem_flg; // 0(阻塞),IPC_NOWAIT, SEM_UNDO
};//对某一个信号灯的操作,如果同时对多个操作,则需要定义这种结构体数组
nops: 要操作的信号灯的个数 ,1个
返回值:成功 :0 ; 失败:-1
用法:semop(semid, &mysembuf, 1);
申请资源 P操作:
mysembuf.sem_num = 0;
mysembuf.sem_op = -1;
mysembuf.sem_flg = 0;
释放资源 V操作:
mysembuf.sem_num = 0;
mysembuf.sem_op = 1;
mysembuf.sem_flg = 0;
3)int semctl ( int semid, int semnum, int cmd…/*union semun arg*/);
功能:信号灯集合的控制(初始化/删除)
参数:semid:信号灯集ID
semnum: 要操作的集合中的信号灯编号
cmd:
GETVAL:获取信号灯的值,返回值是获得值
SETVAL:设置信号灯的值,需要用到第四个参数:共用体
IPC_RMID:从系统中删除信号灯集合
返回值:成功 0 ; 失败 -1
用法:
初始化:semctl(semid, 0, SETVAL, mysemun);
需要在程序中定义共用体
获取信号灯值:semctl(semid, 0, GETVAL);
删除信号灯集:semctl(semid, 0, IPC_RMID);
例子: 简单对信号灯的操作(多值信号灯)
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h> int semid; //信号灯集id, 通过这个id 操作这个信号灯集,在不同进程中,操作同一个信号灯集的id
union semnum
{
int val;
}; union semnum mynum;
struct sembuf mybuf; //定义操作信号灯的结构 //参数 信号灯集id 和 是哪个信号灯
void sem_p(int semid, unsigned short num) //P操作函数
{
mybuf.sem_num = num; //第一个信号灯,(信号灯编号)
mybuf.sem_op = -; //进行P操作, 为 1 时表示V操作
mybuf.sem_flg = ; //阻塞
semop(semid, &mybuf, ); //最后一个参数,表示操作信号灯的个数
} //参数 信号灯集id 和 是哪个信号灯
void sem_v(int semid, unsigned short num) //V操作函数
{
mybuf.sem_num = num;
mybuf.sem_op = ; //1 表示V 操作
mybuf.sem_flg = ; //阻塞
semop(semid, &mybuf, ); //操作的 mybuf 全部变量信号灯集
} int main(int argc, const char *argv[])
{
key_t key;
key = ftok("app",'m');//获取唯一的 key
if(key < )
{
perror("fail fptk ");
exit();
}
//int semget(key_t key, int nsems, int semflg);
//IPC_EXCL | IPC_CREAT 信号灯不存在就创建
semid = semget(key, , IPC_CREAT|IPC_EXCL|); //创建信号灯,IPC_EXCL 问信号灯存不存在
if(semid < )
{
if(errno == EEXIST)//存在时,只需要打开即可
{
semid = semget(key,,); //打开信号灯
}
else
{
perror("semget fail ");
}
}
else
{
// int semctl(int semid, int semnum, int cmd, ...);
mynum.val = ; //设置信号灯值
semctl(semid,,SETVAL,mynum); //初始化 0 号信号灯,此处使用共用体设置信号灯值,初始化完成后可以继续给下一个信号灯设置值 mynum.val = ; //设置信号灯值
semctl(semid,,SETVAL,mynum); //初始化 1 号信号灯,把设置的信号灯值给1号信号灯
}
sem_p(semid, ); //对semid 指向的信号灯集,中0号信号灯进行P操作
sem_p(semid, ); //对semid 指向的信号灯集,中0号信号灯进行P操作
sem_p(semid, ); //对semid 指向的信号灯集,中0号信号灯进行P操作
printf("%d\n",semctl(semid, , GETVAL)); //上面对 0 信号灯初始值 10 进行流三次P 操作,此时应该为 7
printf("%d\n",semctl(semid, , GETVAL)); //没有对 1 信号灯操作,其值不变为 5
putchar(); sem_v(semid,);
printf("%d\n",semctl(semid, , GETVAL)); //上面对 1 信号灯 V 操作,其值变为 6 semctl(semid,,IPC_RMID);//删除信号灯
return ;
}
测试:对于多值信号灯可以进行多次P操作

Linux 进程间通信 信号灯集的更多相关文章
- Linux进程间通信:IPC对象——信号灯集详解
作者:倪老师,华清远见嵌入式学院讲师. 一.信号灯概述 信号灯与其他进程间通信方式不大相同,它主要提供对进程间共享资源访问控制机制.相当于内存中的标志,进程可以根据它判定是否能够访问某些共享资源,同时 ...
- <转>Linux环境进程间通信--信号灯(四)
http://www.ibm.com/developerworks/cn/linux/l-ipc/part4/ 一.信号灯概述 信号灯与其他进程间通信方式不大相同,它主要提供对进程间共享资源访问控制机 ...
- 【转】 Linux进程间通信
一.进程间通信概述进程通信有如下一些目的:A.数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间B.共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别 ...
- (转载)Linux进程间通信
(在学习linux进程通信,看到一篇很好的文章,转载过来,原文地址是http://www.cnblogs.com/linshui91/archive/2010/09/29/1838770.html) ...
- Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存
Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存 参考:<linux编程从入门到精通>,<Linux C程序设计大全>,<unix环境高级编程> ...
- linux进程间通信-(转自 临水)
一.进程间通信概述进程通信有如下一些目的:A.数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间B.共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别 ...
- Linux进程间通信(一): 信号 signal()、sigaction()
一.什么是信号 用过Windows的我们都知道,当我们无法正常结束一个程序时,可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?同样的功能在Linux上是通过生成信号和捕获信号来实现的,运行中 ...
- Linux进程间通信(二):信号集函数 sigemptyset()、sigprocmask()、sigpending()、sigsuspend()
我们已经知道,我们可以通过信号来终止进程,也可以通过信号来在进程间进行通信,程序也可以通过指定信号的关联处理函数来改变信号的默认处理方式,也可以屏蔽某些信号,使其不能传递给进程.那么我们应该如何设定我 ...
- linux进程间通信-概述
一 进程间通信有如下的目的: 1.数据传输,一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M之间:2.共享数据,多个进程想要操作共享数据,一个进程对数据的修改,其他进程应该立刻看到 ...
随机推荐
- java虚拟机规范(se8)——java虚拟机的编译(二)
3.3 算术运算 java虚拟机通常在操作数栈上进行算术运算(例外情况是iinc指令,它直接增加一个局部变量的值).例如下面的align2grain()方法,它的作用是将int值对齐到2的指定次幂: ...
- 【转载】RabbitMQ正确的安装方式(windows10)
链接地址:https://www.cnblogs.com/saryli/p/9729591.html
- linux的锁比较
spinlock spinlock介绍 spinlock又称自旋锁,线程通过busy-wait-loop的方式来获取锁,任时刻只有一个线程能够获得锁,其他线程忙等待直到获得锁.spinlock在多 ...
- spring security学习总结
这几天一直在学习spring security的相关知识.逛各大论坛,看相关api与教学视频,获益良多! 简介 Spring Security是为基于Spring的企业应用系统提供声明式的安全访问控制 ...
- mysql 100%占用的解决
早上客户反应,其网站无法访问,无限转圈 上服务器,查看磁盘空间df -h,内存使用率free -m,网络流量iftop均正常 然后使用top查看时,发现mysql的cpu使用率上升到200%. 解决过 ...
- vue 页面回退mounted函数不执行的问题及解决方法
前言 最近做项目碰到一个很头大的问题--从a页面跳到b页面进行编辑,编辑完再返回a页面,却没走a页面的钩子函数mounted,数据没有更新 经过一番面向百度研究,终于找到了问题所在.接下来就记录一下这 ...
- 6374. 【NOIP2019模拟2019.10.04】结界[生与死的境界]
题目 题目大意 给你一个数列,每次可以选择任意两个相邻的数\(x\)和\(y\),将其删去,并在原来位置插入\(x+2y\). 每次询问一个区间,对这个区间进行上述操作.求最后剩下的数最大是多少. 答 ...
- jq随机生成数字加字母的字符串
html代码: <dl class="row"> <dt class="tit"> <label for="title& ...
- 【NOI2011】兔农(循环节)
我居然没看题解瞎搞出来了? 题解: 不难想到找到每次减1的位置,然后减去它对最终答案的贡献. 假设有一个地方是\(x,1(mod~k)\) 那么减了1后就变成了\(x,0\). 然后可以推到\(x,0 ...
- 管理员技术(七): Linux管理员 综合测试
一.Linux管理员 综合测试 目标: 根据本文提供的练习步骤完成所有练习案例. 方案: 开始练习之前,先依次重置虚拟机环境. [root@room9pc13 ~]# rht-vmctl reset ...