Linux_进程间通信

  • 管道
  • System V 共享内存
  • System V IPC 接口介绍

由于进程地址空间的存在,所以进程间有具有独立性,一个进程看不到另一个进程的数据。那么如果我们想让进程间通信,就必须先让它们先看到同一份资源。常见的进程间通信的方法有管道,System V IPC, POSIX IPC。管道是最古老的一种通信手段,System V ,POSIX 是用于进程间通信的标准。

一.管道

管道的本质是文件,让两个进程看到同一份文件,即指向同一个struct file 结构体,就能让两个进程看到同一份资源,之后就可以开始正常通信了。

1.1 匿名管道

匿名管道就是利用系统调用在程序内创建一个内存级文件(只有struct file结构体),通过父子进程间的继承关系来看到同一份文件。
接口:
image.png

  • 功能:用读写方式打开匿名文件,pipefd[0] 表示读方式打开,pipefd[1] 表示写方式打开

当父进程创建子进程时,子进程会复制大部分父进程的task_struct。故此父进程打开的文件,子进程也能看到。如图:
在这里插入图片描述

由于管道是单向通信,所以我们应该关闭不需要的fd。如果我们想让父进程读,子进程写,则需关闭父进程写端pipefd[1],子进程读端pipefd[0]。之后父进程就可以正常通信了。代码示例如下:

int main()
{int pipefd[2];int n = pipe(pipefd);assert(n != -1);pid_t id = fork();if (id == 0){// 子进程close(pipefd[0]);// 通信代码。。。//通信完毕,关闭文件描述符close(pipefd[1]);exit(0);}// 父进程close(pipefd[1]);// 通信代码。。。。waitpid(id, nullptr, 0);close(pipefd[0]);return 0;
}

特性:

  1. 匿名管道是一种单向通信方式,是半双工的一种特殊情况。
  2. 匿名管道用于具有血缘关系的进程之间通信,比如父子,兄弟
  3. 由于匿名管道是文件,所以生命周期随进程
  4. 面向字节流,当写入的字节数小于PIPE_BUFF(4096)时,保证其原子性,
  5. 由于匿名管道是通过系统调用写入和读出数据,所以自带保护机制(同步)
    1. 当写端退出,读端读完数据后,read系统调用返回0
    2. 当读端退出,写端立即退出,os向写端发送SIGPIPE信号
    3. 当缓冲区空时,读端阻塞等待写端写入数据
    4. 当缓冲区数据满时,写端阻塞等待读端读取数据

1.2 命名管道

匿名管道主要用于具有血缘关系的进程,如果想让两个没有关系的进程通信,就需要用到命名管道,命名管道具有Inode节点,但是没有Data Blocks,不会将数据刷新到磁盘,它只用于进程间通信。创建命名管道有两种方式:1.命令行:mkfifo 指令 2.函数接口mkfifo
接口:

  1. 命令行:mkfifo

image.png

  1. 函数接口mkfifo

在这里插入图片描述

  • pathname:在哪个路径下创建
  • mode:文件的起始权限

需要通信的多个进程中,只要有一个进程创建了命名管道,然后其他进程只需要知道路径,就能满足多个进程看到同一份资源。
代码:
下面构造一个客户端与服务端的代码示例。由服务器端创建命名管道,服务区读,客户端写

#define PATHNAME "./fifo"
// server.c  int main()
{mkfifo(PATHNAME, 0666);int fd = open(PATHNAME, O_RDONLY);// 调用read函数进行读取数据通信close(fd);// 删除管道文件unlink(PATHNAME);return 0;
}//
// client.c  int main()
{int fd = open(PATHNAME, O_WRONLY);// 调用write函数向管道写入数据close(fd);return 0;
}

二.System V 共享内存

进程间通信除了管道,还可以调用系统接口在内存中创建一块共享空间,并且将这块共享空间映射到程序地址空间中(关联),此时进程就可以读写这块空间。共享内存在操作系统内可能有很多,为了便于管理,需要有一个结构体。类似于进程等于内核数据结构+代码,共享内存=内核数据结构+空间。
image.png
ipcs -m 可以查看系统内部的共享内存
ipcrm -m shmid 可以根据shmid删除共享内存

1.接口介绍
  1. 创建共享内存:shmget在这里插入图片描述

image.png

  • key:一个整数,多个进程只要保证调用shmget时,传递相同的key,就可以保证打开同一个共享内存。获取key可以用ftok函数,其中参数是自己设定的
  • size:共享内存的实际可用大小。操作系统分配是以4KB为单位的。
  • shmflg:位图结构体,常用的宏:IPC_CREAT IPC_EXCL,也可以设置共享内存的权限
  • 返回值:返回一个shmid值
  • shmid与key的关系。shmid和key的关系,类似于文件inode编号和fd的关系。key类似于inode编号,shmid类似于fd
    2. 进程与共享内存关联与取消关联

image.png

  • shmat:进程与共享内存关联
    • shmaddr一般设置为空,shmflg一般设置为0
    • 返回值:返回共享内存在虚拟空间中的地址
  • shmdt:
    • 根据虚拟地址将共享内存与进程取消关联
    1. 删除共享内存

在这里插入图片描述

  • shmctl有许多功能,例如查看共享内存结构体的属性,删除共享内存等等,我们重点用这个接口删除共享内存
  • 将cmd参数设置为IPC_RMID ,即可删除对应的共享内存
2.代码示例

三个文件,一个头文件,放函数定义,一个客户端文件,一个服务端文件,服务端创建共享内存和删除共享内存。

#include <iostream>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string>
#include <cstring>
#include <unistd.h>using namespace std;//int shmget(key_t key, size_t size, int shmflg);
//key_t ftok(const char *pathname, int proj_id);const string pathname = ".";
const int proj_id = 0432;
const size_t shmSize = 4096;key_t getKey(const string& pathname, int proj_id)
{return ftok(pathname.c_str(), proj_id);
}// 当shmflg = IPC_CREAT | IPC_EXCL ,表明创建一个共享内存,
//										如果不存在,则创建,存在则报错
int shmHelper(int shmflg)
{key_t key = getKey(pathname, proj_id);int shmid = shmget(key, shmSize, shmflg);cout << shmid << endl;if (shmid == -1){cerr << errno << " : " << strerror(errno) << endl;exit(1);}return shmid;
}int createShm()
{umask(0);return shmHelper(IPC_CREAT | IPC_EXCL|0666); // 不存在则创建,存在则返回shmid
}int getShm()
{return shmHelper(IPC_CREAT);// 不存在则创建,存在则失败返回
}char* attchShm(int shmid)
{// 用法和malloc差不多char* begin = (char*)shmat(shmid, nullptr, 0);if (begin == (void*)-1){cerr << errno << " : " << strerror(errno) << endl;exit(1);}return begin;
}void detachShm(char* begin)
{int n = shmdt(begin);if (n == -1){cerr << errno << " : " << strerror(errno) << endl;exit(1);}
}void destroyShm(int shmid)
{int n = shmctl(shmid, IPC_RMID, nullptr);if (n == -1){cerr << errno << " : " << strerror(errno) << endl;exit(1);}
}
#include"common.hpp"int main()
{// 1. 创建共享内存int shmid = createShm();// 2.与进程关联char* begin = attchShm(shmid);//中间就是通信部分int i = 0;while (true){sleep(3);cout << begin[i++] << endl;i %= 25;sleep(1);}// 3.去关联detachShm(begin);// 4. 销毁共享内存destroyShm(shmid);return 0;
#include"common.hpp"int main()
{// 1. 获取共享内存int shmid = getShm(); // 2.与进程关联char* begin = attchShm(shmid);//通信部分// 共享内存没有保护机制,所以int i = 0;while (true){begin[i++] = 'a'+i;i %= 25;sleep(1);}// 3.去关联detachShm(begin);return 0;

3.共享内存的特点
  1. 大小是以4KB为单位的,比如在shmget中设置size为4087,它会向上对奇到2KB
  2. 速度在众多通信方式中是最快,因为它是直接访问内存,不用经过函数调用
  3. 没有保护机制(同步互斥)。因为不经过系统调用,所以保护机制需要由用户设置

三.System V IPC接口介绍

System V IPC 有三种通信方式:共享内存,消息队列,信号量。由于System V 定义的是一套标准,所以它们的接口都很相似。
命令行中可以用ipcs查看这三种通信方式的属性。也可以用 ipcs -q 查看消息队列,ipcs -s 查看信号量,ipcs -m 查看共享内存。删除命令:ipcrm -m/-s/-q
image.png
下面初步了解一下接口,知道它们的相似性。

1.消息队列
  1. 创建消息队列:msgget

image.png

  1. 发送/接受消息:msgsnd-发送,msgrcv-接收

image.png
其中,msgp需要用户自定义:
image.png

  1. 删除消息队列:msgctl(msqid, IPC_RMID, nullptr)

image.png

2.信号量

信号量(信号灯),可以将它看作一个计数器,表明可用资源的数量。信号量可与共享内存协同工作,每一次申请空间资源时,信号量-1,当信号量为0时,申请资源的进程挂起。当释放空间资源时,信号量+1。

  1. 创建:semget

image.png

  • nsems:一次创建多个信号量
  1. 操作:加1,减1。semop

image.png

  • nsops,指明需要对哪个信号量做操作,默认为0
  • sops,设置操作方式image.png

当sem_op 为-1时,表明信号量做-1操作;当sem_op为1时,表明信号量做+1操作

  1. 删除信号量

image.png

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

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

相关文章

前端学习的笔记第二篇

vscode如何快速生成代码 ! Tab 效果&#xff1a; 解析&#xff1a; <!DOCTYPE html>: 指定当前html版本5。 <html lang"en">: lang > language&#xff0c;en > english。指定当前页面内容是英文的。 <meta charset"UTF-8">:…

猫头虎分享:Win11系统家庭版组策略编辑器怎么打开? Windows11家庭版没有gpedit.msc如何解决?

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

滑动小短剧影视微信小程序源码/带支付收益等模式

仿抖音滑动小短剧影视微信小程序源码&#xff0c;带支付收益等模式、支持无限滑动&#xff1b;高性能滑动、预加载、视频预览&#xff0c;支持剧情介绍&#xff0c;集合壁纸另外仿抖音滑动效果&#xff1b;支持会员模式&#xff0c;支持用户单独购买等等多功能。 丰富的后台设…

深度学习基础之《深度学习介绍》

一、深度学习与机器学习的区别 1、特征提取方面 机器学习&#xff1a;人工特征提取 分类算法 深度学习&#xff1a;没有人工特征提取&#xff0c;直接将特征值传进去 &#xff08;1&#xff09;机器学习的特征工程步骤是要靠手工完成的&#xff0c;而且需要大量领域专业知识…

Golang中的fmt包:格式化输入输出的利器

Golang中的fmt包&#xff1a;格式化输入输出的利器 在软件开发的世界里&#xff0c;fmt包就像是一位忠实的伙伴&#xff0c;始终陪伴着开发人员。它简化了格式化输入输出的过程&#xff0c;让打印和扫描数据变得轻松自如。无论是向控制台输出简单的消息&#xff0c;还是处理复杂…

Rust入门:如何在windows + vscode中关闭程序codelldb.exe

在windows中用vscode单步调试rust程序的时候&#xff0c;发现无论是按下stop键&#xff0c;还是运行完程序&#xff0c;调试器codelldb.exe一直霸占着主程序不退出&#xff0c;如果此时对代码进行修改&#xff0c;后续就没法再编译调试了。 目前我也不知道要怎么处理这个事&am…

数据结构——6.3 图的遍历

6.3 图的遍历 一、概念 图的广度优先遍历 树的广度优先遍历&#xff08;层序遍历&#xff09;&#xff1a;不存在“回路”&#xff0c;搜索相邻的结点时&#xff0c;不可能搜到已经访问过的结点&#xff1a; 若树非空&#xff0c;则根节点入队 若队列非空&#xff0c;队头元素…

C语言——oj刷题——调整数组使奇数全部都位于偶数前面

题目&#xff1a; 输入一个整数数组&#xff0c;实现一个函数&#xff0c;来调整该数组中数字的顺序使得数组中所有的奇数位于数组的前半部分&#xff0c;所有偶数位于数组的后半部分。 一、实现方法&#xff1a; 当我们需要对一个整数数组进行调整&#xff0c;使得奇数位于数…

python系统学习Day1

section1 python introduction 文中tips只做拓展&#xff0c;可跳过。 PartOne introduction 首先要对于python这门语言有一个宏观的认识&#xff0c;包括特点和应用场景。 特点分析&#xff1a; 优势 提供了完善的基础代码库&#xff0c;许多功能不必从零编写简单优雅 劣势 运…

C语言第二十三弹---指针(七)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 指针 1、sizeof和strlen的对比 1.1、sizeof 1.2、strlen 1.3、sizeof 和 strlen的对比 2、数组和指针笔试题解析 2.1、⼀维数组 2.2、二维数组 总结 1、si…

mysql经典4张表问题

1.数据库表结构关联图 2.问题&#xff1a; 1、查询"01"课程比"02"课程成绩高的学生的信息及课程分数3.查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩4、查询名字中含有"风"字的学生信息5、查询课程名称为"数学"&…

单片机学习笔记---AT24C02数据存储

目录 AT24C02数据存储 准备工作 代码讲解 I2C.c 模拟起始位置的时序 模拟发送一个字节的时序 模拟接收应答的时序 模拟接收一个字节的时序 模拟发送应答的时序 模拟结束位置的时序 I2C.h AT24C02.c 字节写&#xff1a;在WORD ADDRESS&#xff08;字地址&#xff…

「Linux」软件安装

MySQL5.7在CentOS安装 安装 配置yum仓库 更新密钥&#xff1a;rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022安装MySQL yum库&#xff1a;rpm -Uvh http://repo.mysql.com//mysql57-community-release-el7-7.noarch.rpm使用yum安装MySQL&#xff1a;yum -y in…

WebSocket原理详解

目录 1.引言 1.1.使用HTTP不断轮询 1.2.长轮询 2.websocket 2.1.概述 2.2.websocket建立过程 2.3.抓包分析 2.4.websocket的消息格式 3.使用场景 4.总结 1.引言 平时我们打开网页&#xff0c;比如购物网站某宝。都是点一下列表商品&#xff0c;跳转一下网页就到了商品…

电动汽车上哪些部位用到了电机?

一、背景 电动汽车中除了主驱动电机之外的其他电机的控制复杂度因电机的种类和功能而异。 一般来说&#xff0c;助力转向电机、空调风扇电机、冷却水泵电机等辅助电机的控制相对较为简单。这些电机通常只需要进行简单的开/关控制或速度调节&#xff0c;以满足车辆的基本需求。…

【实战】一、Jest 前端自动化测试框架基础入门(中) —— 前端要学的测试课 从Jest入门到TDD BDD双实战(二)

文章目录 一、Jest 前端自动化测试框架基础入门5.Jest 中的匹配器toBe 匹配器toEqual匹配器toBeNull匹配器toBeUndefined匹配器和toBeDefined匹配器toBeTruthy匹配器toBeFalsy匹配器数字相关的匹配器字符串相关的匹配器数组相关的匹配器异常情况的匹配器 6.Jest 命令行工具的使…

【Langchain Agent研究】SalesGPT项目介绍(三)

【Langchain Agent研究】SalesGPT项目介绍&#xff08;二&#xff09;-CSDN博客 上节课&#xff0c;我们介绍了salesGPT项目的初步的整体结构&#xff0c;poetry脚手架工具和里面的run.py。在run.py这个运行文件里&#xff0c;引用的最主要的类就是SalesGPT类&#xff0c;今天我…

ARP请求的构造过程

ARP请求的构造过程&#xff1a; ARP请求的构造&#xff1a; 当设备A&#xff08;发起者&#xff09;想要与设备B&#xff08;目标&#xff09;通信&#xff0c;但它只知道设备B的IP地址&#xff08;例如&#xff0c;192.168.1.2&#xff09;&#xff0c;而不知道其MAC地址。设备…

算法沉淀——链表(leetcode真题剖析)

算法沉淀——链表 01.两数相加02.两两交换链表中的节点03.重排链表04.合并 K 个升序链表05.K个一组翻转链表 链表常用技巧 1、画图->直观形象、便于理解 2、引入虚拟"头节点" 3、要学会定义辅助节点&#xff08;比如双向链表的节点插入&#xff09; 4、快慢双指针…

从源码学习访问控制符使用

从源码学习访问控制符使用 Java中的访问控制符 ​ 在Java中&#xff0c;有四个访问控制符&#xff1a;public、protected、default&#xff08;默认或缺省&#xff0c;不使用关键字&#xff09;和private。 ​ 它们的访问范围如下&#xff1a; public&#xff1a;公共访问权…