进程通信知识基础【Linux】——下篇

目录

前文

一,命名管道

创建命名管道

1. getline——c++库

2. unlink——系统接口

实践代码

common.hpp

client.cpp

server.cpp

Log.cpp

二,共享内存(system V接口)

1. 创建共享内存

shmget接口

2. 删除共享内存

常见ipc指令

shmctl接口

3. 映射到虚拟内存(挂起)

shmat接口

去关联

shmdt接口

小结:

三,信号量概念

概念引入 

小结


嘿!收到一张超美的风景图,希望你每天都能开心顺心

 

前文

经过进程池的实践(哈希思想应用【C++】(位图,布隆过滤器,海量数据处理面试题)-CSDN博客),我们对管道有了一定的理解,本篇继续给大家分享其余一些进程通信的知识。

一,命名管道

管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。如果我们想在 不相关的进程之间交换数据,可以使用 FIFO文件来做这项工作,它经常被称为 命名管道
命名管道是一种 特殊类型文件

创建命名管道

在指令端创建

$  mkfifo   filename

在程序中创建

#include <sys/types.h>
#include <sys/stat.h>int mkfifo(const char *pathname, mode_t mode);

其中,pathname管道文件路径mode权限掩码,mkfifo函数返回值为0表示成功-1表示失败,错误原因存储在errno中。

下面我们来一个例子:

创建好一个命名管道后,执行下面指令,我们会遇到光标不动的现象。

echo "hello" > FilePipe

原因是:我们只是向命名管道进行写入没有打开命名管道的读端(从命名管道中读取数据), 进入了一种阻塞状态。(这也是管道的一种控制

解决方法也很简单,就是在另一个窗口,对命名管道进行读数据,这时就会中断写入的阻塞状态。

cat  <  FilePipe 

实践包含一些其他接口:

1. getline——c++库

istream& getline (istream& is, string& str, char delim);

其中,is是输入流,str是存储读取结果的字符串,delim是指定的分隔符(可选,默认为'\n'cin, scanf等是以空格和换行符为分隔符)。函数的返回值是输入流is的引用

getline函数的作用是从输入流is中读取一行文本,并将其存储到字符串str中。如果读取成功,则返回输入流is的引用。如果读取失败,则返回输入流的状态为false。

2. unlink——系统接口

int unlink(const char *pathname);

参数pathname为要删除的文件的路径名。当调用unlink接口时,系统会删除指定路径的文件。如果文件不存在或者无法访问,则会返回-1,并设置errno变量来指示错误类型。

下面头文件中: 

_COMM_H(名字自定义) 宏则是用来防止头文件的重复包含,通过定义这个宏可以在编译过程中检测到头文件是否被多次包含,避免出现重复定义的错误。

实践代码

common.hpp

#ifndef _COMM_H_
#define _COMM_H_
#include <iostream>
#include <vector>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include "Log.hpp"using namespace  std;#define MOODE 0666
#define SIZE 128
#define CHNUMS 3string Pipename = "FilePipe";
string PipeAddress = "./FilePipe";#endif

client.cpp

#include "common.hpp"int main()
{// 1. 客户向服务端,传输请求int fd = open(PipeAddress.c_str(), O_WRONLY);if (fd < 0 ){cout << "open fail" << endl;}string buff;while (1){cout << " Please set your information :> ";getline(cin, buff);  //getline接口的优势在于它可以读取一行文本,并且自动将换行符(\n)作为行结束符write(fd, buff.c_str(), buff.size());}// 关闭命名管道close (fd);// 用户信息读取完后,需要我们删除这个命名管道文件。unlink(Pipename.c_str());//unlink接口是用于删除一个指定的文件或符号链接的系统调用。 return 0;
}

server.cpp

#include "common.hpp"
#include <sys/wait.h>static void Getmessage(int fd) // 设置成静态函数的目的是,让其他文件,无法使用该函数
{char buff[SIZE];Log("处理数据开始", Test) << "[" << getpid() << "] "<< " step 3 " << endl;while (1){memset(buff, '\0', sizeof(buff));ssize_t byte = read(fd, buff, sizeof(buff) - 1);if (byte > 0){cout << "[" << getpid() << "] " << buff << endl;}else if ( byte == 0){cout << " write close " << endl;break;}else{perror(" read fail");cout << "[" << getpid() << "] " << " read error "  << endl;break;}}
}int main()
{// 1. 创建命名管道if (mkfifo(PipeAddress.c_str(), MOODE) < 0 ){perror( " mkfifo fail ");}Log("创建命名管道成功", debug) << "step 1" << endl;// 2. 文件操作int fd = open(PipeAddress.c_str(), O_RDONLY);if (!fd){perror(" open fail");exit(-1);}Log("文件操作成功", debug) << "step 2" << endl;pid_t id;vector<int> FdList;for (int i = 0; i < CHNUMS; i++){id = fork();if (id == 0){Getmessage(fd);exit(1);  // 子进程完美退出,等待父进程接收}}// 父进程接受子进程退出int status = 0;for (int i = 0; i < CHNUMS; i++){// waitpid(FdList[i], nullptr, 0);  这样子写会些坑,不知道哪一个子进程先状态改变waitpid(-1, &status, 0); // -1则是随机等待一个子进程状态改变} // 4. 关闭文件close(fd);unlink(PipeAddress.c_str());Log("关闭文件", warning) << "step 4" << endl;return 0;
}

Log.cpp

#ifndef _LOG_
#define _LOG_
#include <iostream>
#include <ctime>
#include <string>
using namespace std;#define debug 0
#define warning 1
#define Test 2string list_level[3] = {"debug","warning","Test"  
};ostream&  Log(const char* str, int level)
{cout <<  str << " | " << (unsigned)time(0) << " | " << list_level[level] << " ";return cout;
}#endif

下面是上面代码功能的形象图:

二,共享内存(system V接口)

共享内存是一种操作系统进程通信的方式,它允许多个进程共享同一块物理内存区域,从而实现高效的数据交换和共享。

共享内存的原理是将一块物理内存映射到多个进程的虚拟地址空间中,这样多个进程就可以直接读写这块内存,而不需要通过复制数据或者消息传递等方式进行通信

共享内存通常使用信号量来实现进程间的同步和互斥访问。

多个进程共享一块物理内存,操作系统一定得这个操作进行有序管理,而一旦涉及管理,必然要进行 先描述,再组织。

所有共享内存 =  共享内存块 +  对应共享内存块的内核数据结构。

1. 创建共享内存

shmget接口

返回值:一个操作系统运行时,肯定不只一个共享内存,众多的共享内存也被一个内核数据结构管理起来,而返回值就类似文件描述中的fd

1.   int shmflg:  IPC_CREAT(单独用以0替代) and IPC_EXCL 两个宏,前者单独用,共享内存不存在则创建;存在,则返回之。    后者,单独用没有意义,两者通过按位与一起用,底层不存在则创建;存在则出错返回(意义:保证每次共享内存都是最新的)。

2.   key_t key: 我们知道一个操作系统中有众多的共享内存,而key通过特殊的算法规则处理,形成唯一的通行码,找到精确共享内存。

那如何获取 key,通过ftok接口(就是一个对数据进行算法规则处理)。

 

  • pathname:  一个我们可以访问的路径(操作系统会访问其inode值(一个存储标识值)); 
  • proj_id :    就是一个int值。如果想获取一个相同的key值,proj_id也得相同。

返回值:-1失败;大于0则是key值。

3.   size_t size :   共享空间的字节大小。最后是页(4096)的整数倍。原因:假设要4097,则操作系统会创建8192字节,但中间空间我们又无法访问这就是浪费资源了。

2. 删除共享内存

输入指令: 查看共享内存资源

手动删除:

ipcs -m      

然后输入:ipcrm  -m  shmid值

 这里我们要注意的是:共享内存的生命周期随内核!!,除非重启!

perms: 权限值,为0时,谁也无法访问该共享内存,需要在shmget时需要输入权限,比如: shmget(123,  4096 , IPC_CREAT | IPC_EXCL | 0666),权限同文件一样

常见ipc指令

1. ipcs - 显示系统中的IPC资源信息
2. ipcrm - 删除IPC资源
3. ipcs -q - 显示消息队列信息
4. ipcs -s - 显示信号量信息
5. ipcs -m - 显示共享内存信息 

代码删除:

shmctl接口

cmd:  可以理解为功能选项,我们可以选择删除,获取共享空间属性信息等等。IPC_STAT, IPC_RMID等等

shmid:理解为共享内存的标识符吧。

*buf  :  这是管理共享内存的数据结构指针,可用通过buf获取或者修改其属性。

返回值: -1表示失败。

3. 映射到虚拟内存(挂起)

shmat接口

shmid:  共享内存唯一的id 

shmaddr:  去设置一个虚拟地址。(由于我们不清楚虚拟地址的使用情况,这里建议null/nullptr,让计算机来产生

shmflg: 挂接方式,以只读(SHM_R默认0),只写(SHM_W),还是读写(SHM_R | SHM_W )方式挂接。

返回值: 就是计算机返回共享内存虚拟地址的开头; 返回0则失败。

当一旦挂起成功,进程关联数就会增加

去关联

shmdt接口

shmaddr:   共享内存虚拟地址起始地址。 

返回值:-1失败; 0成功,成功删除后同时,进程关联数减一。

成功创建共享内存后位置分布的逻辑图

代码示例:

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>int main() {key_t key = ftok("shmfile",65);  // 创建一个keyint shmid = shmget(key,1024,IPC_CREAT|0666);  // 创建共享内存区char *str = (char*) shmat(shmid,(void*)0,0);  // 将共享内存区连接到当前进程的地址空间printf("Write data : ");gets(str);printf("Data written in memory: %s\n",str);shmdt(str);  // 分离共享内存区shmctl(shmid,IPC_RMID,NULL);  // 删除共享内存区return 0;
}

这里介绍一个比较重要的格式打印数据的接口: snprintf()接口 

小结:

1. 共享内存是进程通信(IPC)中,速度最快的。因为这个方法不需要过多的拷贝数据,而且不用经过操作系统,在用户层直接读取修改。

2. 由于共享内存没有访问控制(读写端独立),容易引发并发问题(两端数据不一致问题)。

三,信号量概念

概念引入 

小结

我们需要理解这个概念

没理解?没事,这个我们在多线程里,用代码的形式进行解释。

下期预告:信号!!

结语

   本小节就到这里了,感谢小伙伴的浏览,如果有什么建议,欢迎在评论区评论,如果给小伙伴带来一些收获请留下你的小赞,你的点赞和关注将会成为博主创作的动力

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

程序员必知!依赖倒置原则的实战应用与案例分析

依赖倒置原则&#xff08;Dependence Inversion Principle&#xff0c;DIP&#xff09;是一种软件设计原则&#xff0c;它要求高层模块不依赖于低层模块&#xff0c;而是依赖于抽象。同时&#xff0c;抽象不依赖于细节&#xff0c;细节应当依赖于抽象。换言之&#xff0c;要针对…

OpenSSL 3.2.0新增Argon2支持——防GPU暴力攻击

1. 引言 OpenSSL新发布的3.20版本中&#xff0c;引入了一些新特性&#xff0c;包括&#xff1a; post-quantum方法Brainpool曲线QUICArgon2&#xff1a;Argon2 是一种慢哈希函数&#xff0c;在 2015 年获得 Password Hashing Competition 冠军&#xff0c;利用大量内存计算抵…

​springboot代码混淆及反混淆代码工具

目录 介绍 什么是混淆 为什么用混淆&#xff1f; 基础混淆 高级混淆工具 #0x1 ipaguard Tool - springboot混淆工具 ipaguard界面概览 ipaguard启动界面 ipaguard代码混淆界面 资源文件混淆界面 重签名界面 尽管到目前为止&#xff0c;这些工具在将代码清理成我们可…

屏幕超时休眠-Android13

屏幕超时休眠-Android13 1、设置界面1.2 属性值1.2.1 默认值1.2.2 最小值限制 1.3 属性值疑问 Settings.System.SCREEN_OFF_TIMEOUT 2、超时灭屏2.1 锁定屏幕的超时2.2 屏幕灭屏的超时 3、永不休眠* 关键日志 1、设置界面 packages/apps/Settings/src/com/android/settings/dis…

上海迅软DSE管控策略大揭秘:如何让企业桌面管理更从容?

随着信息化程度的提高&#xff0c;政企单位在面对愈发复杂且不可控的内网安全问题时&#xff0c;常常因缺乏有效的技术手段而无法建立完善的管理机制&#xff0c;导致企业长期处于被动管理的状态。这使得在发生数据安全事件后&#xff0c;快速而有效地进行处置的能力相对薄弱。…

机器学习——自领域适应作业

任务 游戏里面的话有很多跟现实不一样的情况。 想办法让中间的特征更加的接近&#xff0c;让feat A适应feat B&#xff0c;产生相对正常的输出。 在有标签数据和没有数据的上面进行训练&#xff0c;并能预测绘画图像。 数据集 训练5000张总数&#xff0c;每类有500张测试100…

【二叉树 OJ题】二叉树基础知识 与 OJ题完成(二叉树构建与遍历问题,子树查找问题)

二叉树 &#xff01; 二叉树概念与OJ题完成 二叉树 &#xff01;1 树1.1 树的概念1.2 树的相关概念1.3 树的表示方式 2 二叉树2.1 二叉树的概念2.2 二叉树的构建2.3 特殊的二叉树 3 二叉树OJ题的解决3.1 二叉树构建与遍历问题3.1.1 二叉树遍历3.1.2 二叉树构建3.1.3 题目完成 3…

玩转 TableAgent 数据智能分析

一、什么是数据智能分析&#xff1f; 数据智能分析是指利用先进的技术和工具对大量数据进行收集、整理、分析和挖掘&#xff0c;以获取有益的信息和见解。这种分析通常涉及人工智能、机器学习、数据挖掘和统计分析等技术&#xff0c;旨在揭示数据背后隐藏的模式、关联和趋势&a…

【普中】基于51单片机简易计算器数码管显示设计( proteus仿真+程序+实物演示+讲解视频)

【普中开发板】基于51单片机简易计算器数码管显示设计( proteus仿真程序实物演示讲解视频&#xff09; Proteus 仿真&#xff1a;Proteus 8.16(有低版本) 程序编译器&#xff1a;keil 4/keil 5 编程语言&#xff1a;C语言 设计编号&#xff1a;P04 1. 主要功能&#xff1a…

GAMES101-Homework4

原理&#xff1a;就是上张图片 //该段代码表示四个点的情况&#xff0c;相当于举例子去计算上诉的公式 void naive_bezier(const std::vector<cv::Point2f> &points, cv::Mat &window) {auto &p_0 points[0];auto &p_1 points[1];auto &p_2 poi…

AI数字人直播问题及解决方案!

青否数字人SaaS系统&#xff08;数字人源码&#xff1a;zhibo175&#xff09;目前支持哪些平台使用数字人直播 目前支持的平台有&#xff1a;抖音、快手、视频号、淘宝/天猫、京东、小红书、拼多多&#xff0c;哔哩哔哩&#xff0c;tiktok&#xff0c;阿里国际站&#xff0c;用…

设计模式 简单工厂 工厂方法模式 抽象工厂模式 Spring 工厂 BeanFactory 解析

工厂模式介绍 工厂模式是我们最常用的实例化对象模式了&#xff0c;是用工厂方法代替new操作的一种模式。它是创建型模式。 简单工厂 简单工厂模式是指由一个工厂对象决定创建出哪一种产品类的实例, 但它不属于GOF 23种设计模式 简单工厂适用于工厂类负责创建的对象较少的场景,…

网络管理员推荐的网络监控软件-OpManager

网络是企业背后的基础&#xff0c;这些网络可帮助企业将信息保存在一个集中位置&#xff0c;需要并限制所有其他入站请求的人都可以访问。那么&#xff0c;如何提供持续的一流最终用户体验并维护快速发展的网络呢&#xff1f;只有借助可靠的实时网络监控工具&#xff0c;才能监…

nodejs配置express服务器,运行自动打开浏览器

查看专栏目录 Network 灰鸽宝典专栏主要关注服务器的配置&#xff0c;前后端开发环境的配置&#xff0c;编辑器的配置&#xff0c;网络服务的配置&#xff0c;网络命令的应用与配置&#xff0c;windows常见问题的解决等。 文章目录 设置方法&#xff1a;1&#xff0c;安装nodej…

python实现一张图片按指定宽高截取成多张图片

1、导入所需的包 import os from PIL import Image 2、获取源图片 path_img image img_dir os.listdir(path_img) 3、循环读取源图片并按指定宽高进行自动截图保存 for i in range(len(img_dir)):id img_dir[i].split(.)[0]img Image.open(path_img / img_dir[i])si…

【C++高阶(七)】C++异常处理的方式

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:C从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习C   &#x1f51d;&#x1f51d; 异常处理的方式 1. 前言2. C语言处理异常的方式…

Transformer架构详解

文章目录 引言1. Transformer架构详解1.1 编码器与解码器1.1.1 编码器&#xff08;Encoder&#xff09;1.1.2 解码器&#xff08;Decoder&#xff09; 2. 核心代码2.1 自注意力&#xff08;Self-Attention&#xff09;机制2.2 多头注意力&#xff08;Multi-Head Attention&…

Python PIP安装pycorrector、kemln报错

本来想装个pycorrector用一下&#xff0c;结果在安装其依赖包kemln的时候疯狂报错&#xff0c;报错关键词包括但不限于Bash、Cmake&#xff0c;C啥的&#xff0c;搜了很多文章&#xff0c;终于摸索到了安装的办法。 1、安装bash 去官网https://gitforwindows.org/下载bash&am…

消费者痛点怎么分析,不同行业如何营销

消费者的痛点是品牌营销中的关键因素&#xff0c;因为准确把握消费者的痛点&#xff0c;可以为品牌带来更大的市场机会。今天和大家探讨下消费者痛点怎么分析&#xff0c;不同行业如何营销&#xff1f; 今天我们会从分类、洞察、场景分析、分级与评判以及不同行业细分的角度来进…

neuq-acm预备队训练week 9 P8604 [蓝桥杯 2013 国 C] 危险系数

题目背景 抗日战争时期&#xff0c;冀中平原的地道战曾发挥重要作用。 题目限制 题目描述 地道的多个站点间有通道连接&#xff0c;形成了庞大的网络。但也有隐患&#xff0c;当敌人发现了某个站点后&#xff0c;其它站点间可能因此会失去联系。 我们来定义一个危险系数 DF…