12-LINUX--进程间的通信

进程间通信:采用IPC机制(进程间的用户空间相互独立,内核空间共享),有管道,信号量,共享内存,消息队列,套接字。

一.管道

        管道可以用来在两个进程之间传递数据,如: ps -ef | grep “bash”, 其中‘|’就是管
道,其作用就是将 ps 命令的结果写入管道文件,然后 grep 再从管道文件中读出该数据进行
过滤。

1.1有名管道

        有名管道可以在任意两个进程之间通信
有名管道的创建:
        ◼ 命令创建: mkfifo FIFO
        ◼ 系统调用创建
#include <sys/types.h>
 #include <sys/stat.h>
 //filename 是管道名 mode 是创建的文件访问权限
 int mkfifo(const char *filename, mode_t mode);

a.c代码

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<fcntl.h>

int main()
{
        int fd = open("./fifo",O_WRONLY);
        if(fd ==-1)
        {
                exit(1);
        }
        printf("fd=%d\n",fd);
        while(1)
        {
        printf("intput:\n");
        char buff[128] ={0};
        fgets(buff,128,stdin);
        if(strncmp(buff,"end",3) ==0)
        {
                break;
        }
        write(fd,buff,strlen(buff));
        }
        close(fd);
}
                                                                  

b.c代码

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<fcntl.h>


int main()
{
        int fd = open("./fifo",O_RDONLY);
        printf("fd=%d\n",fd);
        if(fd ==-1)
        {
                exit(1);
        }
        while(1)
        {
        char buff[128];
        int n=read(fd,buff,127);
        if(n==0)
        {
                break;
        }
        printf("buff=%s\n",buff);
        }
        close(0);
        exit(0);
}
      

运行:

1.2无名管道

无名管道主要应用于父子进程间的通信。
无名管道的创建:
1. #include <unistd.h>
2. /*
3. pipe()成功返回 0,失败返回-1
4. fds[0]是管道读端的描述符
5. fds[1]是管道写端的描述符
6. */
7. int pipe(int fds[2]);
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
//无名管到
int main()
{
        int fd[2];//fd[0] r  fd[1]  w
        if(pipe(fd) == -1)
        {
                exit(1);
        }

        write(fd[1],"hello",5);
        char buff[128] ={0};
        read(fd[0],buff,127);
        printf("%s\n",buff);

        close(fd[0]);
        close(fd[1]);
        exit(0);
}

无名管道父子进程间的通信:

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>

int main()
{
	int fd[2];//fd[0] r  fd[1]  w
	if(pipe(fd) == -1)
	{
		exit(1);
	}

	pid_t pid =fork();
	if(pid ==-1)
	{
		exit(1);
	}
	if(pid==0)
	{
		
		close(fd[1]);
		while(1)
		{
			char buff[128]={0};
			//read(fd[0],buff,127);
			if(read(fd[0],buff,127) == 0)
			{
				//printf("child read:%s\n",buff);
				break;
			}
			printf("chlid read:%s\n",buff);

		}
		close(fd[0]);
	}
	else
	{
	        close(fd[0]);
		while(1)
		{
			printf("input: ");
			char buff[128] ={0};
			fgets(buff,128,stdin);
			if(strncmp(buff,"end",3)==0)
			{
				break;
			}
			write(fd[1],buff,strlen(buff));
		}
		close(fd[1]);
	}
	exit(0);
}

1.3管道的特点

无论有名还是无名,写入管道的数据都在内存中
管道是一种半双工通信方式(通信方式有单工、半双工、全双工)
有名和无名管道的区别:有名可以在任意进程间使用,而无名主要在父子进程间

1.4管道的实现

二.信号量

由于父子进程间无法确定谁先谁后,所以运行结果会有顺序错乱的情况

提出使用信号量管理,使得父子进程间的通信变得有序

1.信号量

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

2.信号量的使用

操作信号量的接口介绍:
 #include <sys/sem.h>
 #include <sys/types.h>
 #include <sys/ipc.h>
 /*
 semget()创建或者获取已存在的信号量
 semget()成功返回信号量的 ID, 失败返回-1
 key:两个进程使用相同的 key 值,就可以使用同一个信号量
 nsems:内核维护的是一个信号量集,在新建信号量时,其指定信号量集中信号
量的个数
 semflg 可选: IPC_CREAT IPC_EXCL
 */
 int semget(key_t key, int nsems, int semflg);

 /*
 semop()对信号量进行改变,做 P 操作或者 V 操作
 semop()成功返回 0,失败返回-1
 struct sembuf
 {
 unsigned short sem_num; //指定信号量集中的信号量下标
 short sem_op; //其值为-1,代表 P 操作,其值为 1,代表 V 操作
 short sem_flg; //SEM_UNDO
 };
 */
 int semop(int semid, struct sembuf *sops, unsigned nsops);
 /*
 semctl()控制信号量
 semctl()成功返回 0,失败返回-1
 cmd 选项: SETVAL IPC_RMID

 union semun
 {
 int val;
struct semid_ds *buf;
 unsigned short *array;
 struct seminfo *_buf;
 };
 */
int semctl(int semid, int semnum, int cmd, ...);
例题:进程 a 和进程 b 模拟访问打印机,进程 a 输出第一个字符‘a’表示开始使用打印
机,输出第二个字符‘a’表示结束使用,b 进程操作与 a 进程相同。(由于打印机同一时刻
只能被一个进程使用,所以输出结果不应该出现 abab),如图所示:

封装信号量的接口:

          sem.h 的代码如下:
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/sem.h>

union semun
{
	int val;
};
void sem_init();
void sem_p();
void sem_v();
void sem_destroy();
sem.c 的代码如下:
#include "sem.h"

static int semid =-1;
void sem_init()
{
	semid =semget((key_t)1234,1,IPC_CREAT|IPC_EXCL|0600);
	if(semid == -1)
	{
		semid = semget((key_t)1234,1,IPC_CREAT|0600);//创建失败,说明已有,获取
		if(semid == -1)
		{
			printf("semget err\n");
			return;
		}
	}
	else//创建成功,初始化
	{
	 	union semun a;
		a.val =1;
		if(semctl(semid,0,SETVAL,a) == -1)
		{
			printf("semcrl setval err\n");
		}
	}
}
void sem_p()
{
	struct sembuf buf;
	buf.sem_num =0; //信号两的下标,目前只有一个,下标为0
	buf.sem_op =-1;//p
	buf.sem_flg = SEM_UNDO;

	if(semop(semid,&buf,1) == -1)
	{
		printf("semop p err\n");
	}
}
void sem_v()
{
	
	struct sembuf buf;
	buf.sem_num =0; //信号两的下标,目前只有一个,下标为0
	buf.sem_op =1;//v
	buf.sem_flg = SEM_UNDO;

	if(semop(semid,&buf,1) == -1)
	{
		printf("semop v err\n");
	}
}
void sem_destroy()//销毁信号量
{
	if(semctl(semid,0,IPC_RMID) == -1)
	{
		printf("semctl destroy err\n");
	}
}
a.c 的代码如下:
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/sem.h>
#include"sem.h"
int main()
{
	sem_init();
	for(int i =0;i<5;i++)
	{
		sem_p();
		printf("A");
		fflush(stdout);
		int n = rand() %3;
		sleep(n);
		printf("A");
		fflush(stdout);;
		sem_v();
		n=rand() %3;
		sleep(n);
	}
}
//gcc -o a a.c sem.c
//gcc -o b b.c sem.c 

b.c代码:

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/sem.h>
#include"sem.h"
int main()
{
	sem_init();
	for(int i =0;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);
	}
	sleep(10);
	sem_destroy();
}
运行结果如下图所示,输出结果只截了部分:
练习题: 三个进程 a、b、c 分别输入“A”、“B”、“C”,要求输出结果必须是“ABCABCABC…”

3.ipcs/ipcrm 介绍

ipcs 可以查看消息队列、共享内存、信号量的使用情况,使用 ipcrm 可以进行删除操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/542822.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java8 收集Stream流中的结果

目录 Stream流中的结果到集合中 Stream流中的结果到数组中 对流中数据进行聚合计算 1. 获取最大值 2. 获取最小值 3. 求总和 4. 平均值 5. 统计数量 对流中数据进行分组 对流中数据进行多级分组 对流中数据进行分区 对流中数据进行拼接 Stream流中的结果到集合中 …

Facebook广告投放数据API对接流程

说明&#xff1a;仅供学习使用&#xff0c;请勿用于非法用途&#xff0c;若有侵权&#xff0c;请联系博主删除 作者&#xff1a;zhu6201976 一、需求背景 App在Facebook、Google等巨头进行广告投放&#xff0c;想要拿到实时广告投放效果数据&#xff0c;如曝光、点击、花费、触…

mybatis(5)参数处理+语句查询

参数处理&#xff0b;语句查询 1、简单单个参数2、Map参数3、实体类参数4、多参数5、Param注解6、语句查询6.1 返回一个实体类对象6.2 返回多个实体类对象 List<>6.3 返回一个Map对象6.4 返回多个Map对象 List<Map>6.5 返回一个大Map6.6 结果映射6.6.1 使用resultM…

流氓软件清理绝杀全家桶

下载地址&#xff1a;流氓软件清理绝杀全家桶.zip 网上仍有不少软件中携带流氓软件&#xff0c;甚至某些所谓的大厂出品的工具中也会有一些捆绑&#xff01; 对于玩机经验不太丰富的小白来说&#xff0c;也许一不小心&#xff0c;桌面就会被某些流氓软件搞得乌烟瘴气&#xf…

【每日刷题】技巧合集-LC136、LC169

1. LC136.只出现一次的数字 题目链接 解法一&#xff1a; 先给数字排序&#xff0c;如果num[i]与nums[i-1]或nums[i1]都不一致&#xff0c;则返回nums[i]。 class Solution {public int singleNumber(int[] nums) {if (nums.length 1){return nums[0];}Arrays.sort(nums);fo…

RabbitMQ消息模型之Work消息模型

Work消息模型 * work模型&#xff1a; * 多个消费者消费同一个队列中的消息&#xff0c;每个消费者获取到的消息唯一&#xff0c;且只能消费一次 * 作用&#xff1a;提高消息的消费速度&#xff0c;避免消息的堆积 * 默认采用轮询的方式分发消息 * 如果某…

多张固定宽度元素,随着屏幕尺寸变化自动换行

背景&#xff1a;多张固定宽度元素&#xff0c;随着屏幕尺寸变化自动换行实现&#xff1a; <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevic…

加速Python循环的12种方法,最高可以提速900倍

在本文中&#xff0c;我将介绍一些简单的方法&#xff0c;可以将Python for循环的速度提高1.3到900倍。 Python内建的一个常用功能是timeit模块。下面几节中我们将使用它来度量循环的当前性能和改进后的性能。 对于每种方法&#xff0c;我们通过运行测试来建立基线&#xff0…

如何监控容器或K8s中的OpenSearch

概述 当前 OpenSearch 使用的越来越多, 但是 OpenSearch 生态还不尽完善. 针对如下情况: 监控容器化或运行在 K8s 中的 OpenSearch 我查了下, 官方还没有提供完备的方案. 这里如何监控 K8s 中的 OpenSearch, 包括安装 exporter 插件、采集、展示全环节。 OpenSearch 简介…

RTL设计指导原则

RTL设计指导原则 一、面积与速度互换原则 1. 电路设计中的面积与速度 面积&#xff1a;设计所消耗的目标器件的硬件资源数量或者ASIC芯片的面积。 FPGA&#xff1a;所消耗的触发器(FF&#xff09;和查找表&#xff08;LUT)数量来衡量; ASIC&#xff1a;设计的面积、门数等衡…

【免安装的MATLAB--MATLAB online】

目录&#xff1a; 前言账号的注册图片处理的示例准备图片脚本函数 总结 前言 在计算机、数学等相关专业中&#xff0c;或多或少都会与MATLAB产生藕断丝连的联系&#xff0c;如果你需要使用MATLAB&#xff0c;但是又不想要安装到自己的电脑上&#xff08;它实在是太大了啊&#…

华为海思数字芯片设计笔试第四套

声明 下面的题目作答都是自己认为正确的答案&#xff0c;并非官方答案&#xff0c;如果有不同的意见&#xff0c;可以评论区交流。 这些题目也是笔者从各个地方收集的&#xff0c;感觉有些题目答案并不正确&#xff0c;所以在个别题目会给出自己的见解&#xff0c;欢迎大家讨论…

L1-041 寻找250

对方不想和你说话&#xff0c;并向你扔了一串数…… 而你必须从这一串数字中找到“250”这个高大上的感人数字。 输入格式&#xff1a; 输入在一行中给出不知道多少个绝对值不超过1000的整数&#xff0c;其中保证至少存在一个“250”。 输出格式&#xff1a; 在一行中输出第一次…

【架构-8】Lambda和Kappa架构

Lambda架构&#xff1f; Lambda架构&#xff08;三层架构&#xff09;&#xff1a; &#xff08;1&#xff09;将数据处理分为实时和离线两部分。离线部分通过批量计算处理数据&#xff0c;实时部分则通过增加追加方式将数据合并到批处理中。 &#xff08;2&#xff09;批处理…

js canvas实现裁剪图片并下载

简历上给自己挖的坑&#xff0c;面试被拷打&#xff0c;早就该填了T.T 参考&#xff1a;【js canvas实现图片裁剪】 https://www.bilibili.com/video/BV1QK411d7n1/?share_sourcecopy_web&vd_sourcebf743b20b76eab11028ba2fb05f056b4 效果 思路 组成&#xff1a; 上传文…

基于Springcloud可视化项目:智慧工地可视化大数据云平台源码

目录 技术架构 智慧工地系统在实际推行过程中遇到的问题 智慧工地接纳程度较低 基础设施条件有待完善 智慧工地整体生态尚未完善 智慧工地平台各功能模块 施工过程工信程息信管息理管模理块 人员管理模块 生产管理模块 技术管理模块 质量管理模块 安全管理模块 绿…

记录一个Kafka客户端Offset Explore连不上的问题

我昨天把集群重装了一下&#xff0c;再连这个工具就连不上了&#xff08;你先把zk和kafka在集群启起来&#xff09;&#xff0c;报错截图如下&#xff1a; 英文翻译过来大概就是说遍历zk指定路径不存在&#xff0c;我还以为zk的问题&#xff0c;回去又把zk的文档翻了一遍&#…

多线程代码案例之阻塞队列

目录 1.生产者消费者模型 2.使用标准库中的阻塞队列 3.模拟实现阻塞队列 在介绍阻塞队列之前&#xff0c;会先介绍一些前置知识&#xff0c;像队列&#xff1a;有普通队列、优先级队列、阻塞队列、和消息队列。前面两个是线程不安全的&#xff0c;而后面两个是线程安全的。本…

FFmpeg: 自实现ijkplayer播放器--03UI界面设计

文章目录 UI设计流程图UI设计界面点击播放功能实现 UI设计流程图 UI设计界面 主界面 控制条 播放列表 画面显示 标题栏 设置界面 提示框 点击播放功能实现 槽函数实现&#xff1a; connect(ui->ctrlBarWind, &CtrlBar::SigPlayOrPause, this, &Main…

软件杯 深度学习卷积神经网络垃圾分类系统 - 深度学习 神经网络 图像识别 垃圾分类 算法 小程序

文章目录 0 简介1 背景意义2 数据集3 数据探索4 数据增广(数据集补充)5 垃圾图像分类5.1 迁移学习5.1.1 什么是迁移学习&#xff1f;5.1.2 为什么要迁移学习&#xff1f; 5.2 模型选择5.3 训练环境5.3.1 硬件配置5.3.2 软件配置 5.4 训练过程5.5 模型分类效果(PC端) 6 构建垃圾…