1、IPC机制:

进程间通信(管道、信号量、共享内存、消息队列、套接字)

2、信号量:

可以类比于红绿灯,对于路口这个共享的通行权,谁得到红绿灯的通行信号,才可以得到路口的通行权,没得到通信信号,就只能等待。

1)信号量的定义:

信号量是一个原子操作,例如+1、-1,不能被打断,只有等其操作完才能去使用。这里的+1 、 -1类比于资源的释放和获取,为二值信号量,只有两个值,其初始值为1,就只有0和1两个值。

定义:

信号量是一个特殊的变量,一般取正数值。它的值代表允许访问的资源数目, 获取资源时,需要对信号量的值进行原子减一,该操作被称为 P 操作。当信号量值为 0时,代表没有资源可用, P 操作会阻塞。释放资源时,需要对信号量的值进行原子加一,该操作被称为 V操作。信号量主要用来同步进程。 信号量的值如果只取 0,1,将其称为二值信号量。如果信号量的值大于 1,则称之为计数信号量。注意:正数值; 加一减一是一个原子操作;

2)临界资源和临界区的概念:

临界资源:计算机的软硬件资源,即同一时刻,只允许一个进程或者线程访问的资源;
临界区:访问临界资源的代码段;

2、信号量的一个例子

不加控制模拟使用打印机:
比如:进程 a 和进程 b 模拟访问打印机,进程 a 输出第一个字符‘ a’表示开始使用打印机,输出第二个字符‘ a’表示结束使用, b 进程操作与 a 进程相同。(由于打印机同
一时刻只能被一个进程使用,所以输出结果不应该出现 abab这样交替的结果)

代码示例:
a.c

//a.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
int main()
{int i=0;for(;i<5;i++){printf("A");fflush(stdout);int n=rand()%3;sleep(n);printf("A");fflush(stdout);n=rand()%3;sleep(n);}
}

b.c:

//b.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
int main()
{int i=0;for(;i<5;i++){printf("B");fflush(stdout);int n=rand()%3;sleep(n);printf("B");fflush(stdout);n=rand()%3;sleep(n);}
}

3、信号量的接口

(1)semget --创建或者获取一个已经存在的信号量

参数:

int semget(key_t key,int nsems,int semflg);

(key_t 其实为int类型,只不过)

key:给相同的key值,能得到相同的信号量。
nsems:创建几个信号量;
semflg:标志位,如果为创建:IPC_CREAT;
–如果为创建:为IPC_CREAT;
–如果为全新创建,也就是不知道是否有人创建过,则 IPC_CREATE | IPC_EXCL ,就是如果没有则创建,如果有则创建失败;

(2)semop --对信号量进改变,做p操作或者v操作;

p操作为获取资源;
v操作为释放资源;

参数:

int semop(int semid,struct sembuf *sops,unsigned nsops);

nsops :为结构体长度

semid:信号量的id号,也就是刚才semget的返回值;4;说明对哪个信号量进行操作;
sops:结构体指针,指向sembuf的结构体指针,

sembuf 结构体有三个成员变量:
sem_num 表示信号量的编号(即指定信号量集中的 信号量下标);
sem_op 表示是p还是v操作;1为v操作(加1),-1为p操作(减1);
sem_flg 为标志位;

(3)semct --对信号量进行控制;

参数:

int semctl(int semid,int semnum,int cmd,...);

semid:信号量id;
semnum:信号量编号;
cmd:命令:SETVAL:初始化信号量; IPC_RMID:删除信号量;

注意:联合体semun,这个联合体需要自己定义;

思路:

4、控制打印机的代码如下:

1)基础代码

a.c :

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>int main()
{int i = 0;for(;i < 5;i++){printf("A");fflush(stdout);int n = rand()%3;sleep(n);printf("A");fflush(stdout);n = rand()%3;sleep(n);}
}

b.c :

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>int main()
{int i = 0;for(;i < 5;i++){printf("B");fflush(stdout);int n = rand()%3;sleep(n);printf("B");fflush(stdout);n = rand()%3;sleep(n);}
}

同时运行(加&,后台运行):./a& ./b&
结果不一定完全相同,但都是成块出现,都是两个A两个B

2)思路


代码实现:

sem.h

//sem.h
#include <sys/sem.h>
#include <unistd.h>
#include <stdio.h>union semun
{int val;
};void sem_init();
void sem_p();
void sem_v();
void sem_destroy();

sem.c

//sem.c
#include "sem.h"static int semid=-1;//信号量的初始化实现
void sem_init()
{semid=semget((key_t)1234,1,IPC_CREAT|IPC_EXCL|0600);//1234为自己定义的if(semid==-1)//全新创建失败{semid=semget((key_t)1234,1,0600);//获取已经存在的信号量if(semid==-1)//获取再失败,是真的错了{perror("semget error");}}else//全新创建成功{//初始化union semun a;a.val=1;if(semctl(semid,0,SETVAL,a)==-1)//初始化,只有一个信号量,所以为0{perror("semctl init error");}}
}//p操作
void sem_p()
{struct sembuf buf;buf.sem_num=0;buf.sem_op=-1;//p操作buf.sem_flg=SEM_UNDO;//相当于操作系统记住你进行了p操作,如果异常结束,无法进行v操作,系统会帮你操作if(semop(semid,&buf,1)==-1)//出错处理{perror("p error");}
}//v操作
void sem_v()
{struct sembuf buf;buf.sem_num=0;buf.sem_op=1;//v操作buf.sem_flg=SEM_UNDO;//相当于操作系统记住你进行了p操作,如果异常结束,无法进行v操作,系统会帮你操作if(semop(semid,&buf,1)==-1)//出错{perror("v error");}
}//销毁操作
void sem_destroy()
{if(semctl(semid,0,IPC_RMID)==-1)//0表示占位{perror("destroy sem error");}
}

a.c

//a.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include "sem.h"
int main()
{int i=0;sem_init();for(;i<5;i++){//p v 操作之间为临界区,访问临界资源的代码段sem_p();printf("A");fflush(stdout);int n=rand()%3;sleep(n);printf("A");fflush(stdout);sem_v();n=rand()%3;sleep(n);//sem_v();可以放在此代码之后,但不好,效率过低}sleep(10);sem_destroy();//如果忘记销毁,或者程序出错,信号量可能还在,需要通过ipcs查看
}

b.c

//b.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include "sem.h"
int main()
{int i=0;sem_init();for(;i<5;i++){sem_p();printf("B");fflush(stdout);int n=rand()%3;sleep(n);printf("B");fflush(stdout);sem_v();n=rand()%3;sleep(n);}
}

5、三个进程分别输出"A"、“B”、“C”,要求输出结果必须是"AABBCCAABB…"

思路如下:

三、ipcs 命令 – 查看信号量、消息队列和共享内存

ipcs :


运行./a& ./b& 之后

其中4d2,为1234
对应代码semid=semget((key_t)1234,1,IPC_CREAT|IPC_EXCL|0600);

ipcs -s :只查看信号量

ipcs -m :只查看共享内存

ipcs -q :只查看消息队列

ipcrm -s 编号 :删除信号量

Linux15 --- 信号量、ipcs相关推荐

  1. linux无法释放信号量ipcs,Linux系统中的ipcs命令使用详解

    用途 报告进程间通信设施状态. 语法 复制代码 代码如下: ipcs [-mqs] [-abcopt] [-C core] [-N namelist] -m 输出有关共享内存(shared memor ...

  2. 判断sem信号量为零_kernel.sem信号量调优

    一.kernel.sem 信号量 sem其实是semaphores的缩写,这个在oracle数据库配置的时候,会需要调整该值,对于一般的程序来说基本是用不到的.不过现网中也遇到过个别主机上zabbix ...

  3. linux ipcs 命令详解

    ipcs - 分析消息队列.共享内存和信号量 ipcs - report status of interprocess communication facilities ipcs displays c ...

  4. 临界资源、临界区、信号量、P,V操作

    一.资源: Linux上有硬件资源和软件资源之分.程序会受到资源限制的影响,可能在这几方面的资源限制受到影响:1.硬件方面的物理性限制(内存):2.系统策略的限制(允许使用的CPU时间):3.具体实现 ...

  5. ipcs 查看IPC 对象信息

    ipcs 命令 查看 Message Queue,Shared Memory , Semaphore 对象信息 ipcs -s ,擦看信号量 ipcs -m,查看共享内存 ipcs -q,查看消息队列 ...

  6. shmget创建共享内存errno - ipcs - From

    Thanks to: https://blog.csdn.net/libaineu2004/article/details/76919711 今天编写的程序,要使用一个共享内存,共享内存是由别的进程创 ...

  7. linux ipcs命令详解

    ipcs命令 ipcs -a :显示全部可以显示的信息 ipcs -q:显示活动的消息队列 ipcs -m:显示活动的共享内存信息 ipcs -s:显示活动的信号量信息 ipcrm命令: ipcrm ...

  8. ipcs ipcrm

    ipcs和ipcrm用法简介 命令名称:ipcs 使用权限:所有使用者 使用方式: ipcs [-m|-q|-s] -m       输出有关共享内存(shared memory)的信息 -q     ...

  9. linux进程间通信-XSI IPC

    一 什么是XSI IPC 有三种 IPC我们称作XSI IPC,即消息队列.信号量以及共享存储器(共享内存),它们之间有很多相似之处. 二 标识符和键     每个内核中的 IPC结构(消息队列.信号 ...

最新文章

  1. [Selenium] 操作浏览器 Cookies
  2. Talend Restful
  3. C#中String与Datetime
  4. python issubclass 和 isinstance函数
  5. HDFS上传文件报错java.lang.InterruptedException
  6. Linux CentOS 7 YouCompleteMe相关配置。
  7. 金蝶k3单据编码规则_金蝶K3存货跌价案例教程
  8. 计算机技术基础 VB 答案,《计算机技术基础(VB)》武汉理工大学20春作业一
  9. 看到程序员坐在电脑前,如何判断程序员正在做什么?只需看这些
  10. 交叉编译openwrt php,交叉编译n2n,以openwrt为例子
  11. –is-dba_查询存储–每个DBA的下一代工具
  12. 用Windows Live Writer写51cto博客
  13. 基于fo-dicom 的 Worklist CStore 我的学习实现路线
  14. CIC滤波器原理及设计实现
  15. 【测试】echo发送和接收TCP/UDP数据包|shell 发送TCP/UDP数据包
  16. android 常用软件包
  17. 常见java空指针异常
  18. ARM和Intel处理器区别简介
  19. java 读取pdf签名域_Java 获取PDF中的数字签名信息
  20. Python核心编程(第3版)第2章网络编程中关于tcp/udp服务器和客户端实现代码的运行出错的修正

热门文章

  1. 丁晓钟怎么样_六级答案_丁晓钟:如何从各个角度学习四六级阅读理解?_沪江英语...
  2. 非主流Linux窗口管理器集锦
  3. java毕业设计小型酒店管理系统源码+lw文档+mybatis+系统+mysql数据库+调试
  4. 吃鸡国际服手游怎么总说服务器无响应,吃鸡国际服玩家卖号回血,暴露射击游戏的弊端,可惜已经太迟!...
  5. MySQL官网下载方法
  6. idea报错:please specify commit message
  7. EE架构|国内主流OEM的中央计算+区域控制架构信息梳理
  8. scp远程服务器拷贝到远程服务器
  9. Linux环境下实现excel文件转pdf并且实现优化
  10. 入侵电网的现实与真相