【Linux操作系统】进程间通信(1)

目录

  • 一、认识进程间通信
  • 二、匿名管道
  • 三、命名管道

一、认识进程间通信

进程间不能直接传递数据,因为进程具有独立性,直接传递会破坏进程的独立性。

进程间通信是什么?

一个进程把自己的数据交给另一个进程。

为什么要有进程间通信?

需要多个进程协同,共同完成一些事(数据共享、资源共享、通知事件、进程控制)

怎么做?

先让不同的进程看到同一份资源,这个同一份资源由操作系统提供。交换数据的内存,不能由通信双方的任何一个提供。

具体:因为操作系统提供空间有不同的方式,所以有不同的通信方式——管道、共享内存、消息队列、信号量

二、匿名管道

一个进程的PCB对象里面有指向files_struct类型结构体的指针,该结构体里面有文件描述符表,0-2分别指向的是系统默认打开的标准输入、标准输出和标准错误。当往一个文件(磁盘中的log.txt)写入数据,然后读取数据,共两次操作,struct file会有两个,一个是写的,另一个是读的(不同指针指向同一个文件)。w操作调用系统接口,将写入的数据给缓冲区,然后再刷新到磁盘的文件中;r操作,磁盘的文件的数据先到缓冲区,然后对应的系统接口再把数据读取出来。总之,写入和读取都是在缓冲区进行的,因为缓冲区也是内存,调用系统接口,就是运行某个程序,程序和磁盘中文件要加载到内存。如果让当前进程fork后创建一个子进程,那么子进程的文件描述符表里面的下标3和4也指向父进程指向的struct file,files_struct是进程的属性之一,所以创建子进程时子进程的PCB对象也有files_struct,而struct file是文件系统的,就一份。因此,此时的父子进程如图指向struct file的w文件和r文件,w和r指向同一个内存缓冲区,然后再到磁盘中的一个文件log.txt。
在这里插入图片描述
既然有创建子进程,就是要子进程办事的,如果让子进程w,父进程r,那么,子进程写的通过缓冲区刷新到磁盘文件中(写的时候,文件要先被加载到内存,即缓冲区,),然后,父进程通过缓冲区读取文件的信息(也是在缓冲区,即内存中。不管读写,都要先将文件加载到内存执行)。这样,子进程写的,父进程就能看到,所以,在这里父子进程通过缓冲区,即一块内存,就能够看到同一份资源的,这种方式或者说是通信方式就叫管道。

管道只能是单向通信。父进程最开始时的权限是rw,因为这样给子进程也是rw,然后关闭权限(父进程关闭w,子进程关闭r,注意,父进程刚开始不能只有一个r或w,因为不能新打开权限),一个读,一个写。

为了实现管道通信,OS提供了系统调用pipe() 。pipefd数组得到两个fd,分别是读r和写w(输出型参数)
在这里插入图片描述
特点:不需要向磁盘刷新内容,它不是一个文件,磁盘中也不存在这个文件。也就是说它会有一块内存,但是与磁盘无关,它是一个内存级文件,没有名字,是匿名的,一般就叫它——管道。

匿名管道如何让不同的进程看到同一份资源?创建子进程,子进程继承父进程相关的属性信息。只能具有“血缘”关系的进程可以进程间通信,常用于父子进程。

代码:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/wait.h>void reader(int rfd)
{char buffer[1024];while(1){ssize_t n = read(rfd, buffer, sizeof(buffer));printf("message: %s\n", buffer);sleep(1);}
}
void writer(int wfd)
{char* str = "I am father";char buf[1024];int cnt = 1;pid_t pid = getpid();while(1){snprintf(buf, sizeof(buf), "message: %s, pid: %d, cnt: %d", str, pid, cnt);write(wfd, buf, sizeof(buf));cnt++;sleep(1);}
}
int main()
{//1、创建管道int pipefd[2];int n = pipe(pipefd);if(n < 0) return 1;//2、创建子进程pid_t id = fork();if(id == 0){//子进程读close(pipefd[1]);//关闭写reader(pipefd[0]);//读exit(0);}//父进程写close(pipefd[0]);//关闭读writer(pipefd[1]);//写wait(NULL);//防止僵尸return 0;
}

在这里插入图片描述
4种情况:一、管道内部没有数据,并且写端没有关闭,那么读端就要阻塞等待,直到pipe有数据;二、管道内部被写满,并且读端不关闭,那么写端写满之后,就要阻塞等待;三、对于写端,不写了,并且管道关闭,那么读端会把管道内的所有数据读完,最后读到返回值为0,表示读结束;四、读端不读并且关闭,写端在写,那么操作系统就会直接终止写入的进程

5种特性:一、自带同步机制(管道内部有数据,读端就读,没有就等待;管道没有写满,写端就写,满了就等待);二、血缘关系进程间通信,常见于父子进程;三、pipe是面向字节流的(写可能是一个一个的写,但是读可以一次性全部读出来);四、父子进程退出,管道自动释放,文件的生命周期是随进程的;五、管道只能单向通信。

命令行管道| 本质是匿名管道

三、命名管道

两个特点:1、让不同进程看到同一份资源;2、让没有亲缘关系的进程可以进行通信
在这里插入图片描述

怎么保证两个不同的进程打开的是同一个文件?找到文件:文件名+文件路径

系统调用接口:mkfifo、unlink
在这里插入图片描述
在这里插入图片描述

验证代码:
两个不相干的进程,一个发送消息,另一个接收

Comm.hpp

#ifndef __COMM_HPP__
#define __COMM_HPP__#include <iostream>
#include <unistd.h>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <cstdlib>
#include <fcntl.h>using namespace std;
#define Mode 0666
#define Path "fifo"class Fifo
{
public:Fifo(const string &path) : _path(path){umask(0);//创建管道int n = mkfifo(_path.c_str(), Mode);if(n == 0){cout << "fifo create success" <<endl;}else {cout << "fifo fail, errno: " << errno << " stringerrno: " << strerror(errno) << endl;}}~Fifo(){//删除管道,管道也是文件int n = unlink(_path.c_str());if(n == 0){cout << "fifo remove success" <<endl;}else {cout << "fifo remove, errno: " << errno << " stringerrno: " << strerror(errno) << endl;}}private:string _path;//文件名+文件路径
};#endif

pipeServer.cc

#include "Comm.hpp"int main()
{Fifo fifo(Path);//实例化//打开文件int rfd = open(Path, O_RDONLY);if(rfd < 0){cout << "open fail, errno: " << errno << " stringerrno: " << strerror(errno) << endl;return 1;}char buffer[1024];while(true){ssize_t n = read(rfd, buffer, sizeof(buffer)-1);if(n > 0)//读取成功{buffer[n] = 0;cout << "message: " <<buffer<<endl;}else if(n == 0)//读停止 {cout << "read quit.. " <<endl;break;}else //读失败{cout << "read fail, errno: " << errno << " stringerrno: " << strerror(errno) << endl;break;}}close(rfd);//关闭文件return 0;
}

pipeClient.cc

#include "Comm.hpp"int main()
{//打开文件int wfd = open(Path, O_WRONLY);if(wfd < 0){cout << "open fail, errno: " << errno << " stringerrno: " << strerror(errno) << endl;return 1;}string buffer;while(true){cout << "Please message# ";getline(cin, buffer);ssize_t n = write(wfd, buffer.c_str(), buffer.size());if(n < 0){cout << "write fail, errno: " << errno << " stringerrno: " << strerror(errno) << endl;break;}}close(wfd);//关闭文件return 0;
}

在这里插入图片描述

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

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

相关文章

DAG计算框架:实现业务编排

文章目录 DAG如何实现DAG计算框架Node的实现Engine的实现Graph的实现具体某个节点如何使用 在工作几年之后&#xff0c;大部分人如果还在继续做着 CRUD的简单重复工作&#xff0c;即使领导不提出对你更高的期望&#xff0c;自身也会感到焦虑吧。学如逆水行舟不进则退&#xff…

怎么整合spring security和JWT

什么是spring security spring security是一个安全框架,它里面有过滤器链,可以多次过滤,其实他可以给前端的cookie传入一个jsessionid,都可以不使用jwt也能完成校验 第一步:导入依赖 <!-- springboot security --> <dependency><groupId>org.springframew…

git错误fatal: Unpack error, check server log

git错误fatal: Unpack error, check server log fatal: Unpack error, check server log error: remote unpack failed: error Missing tree xxxxxxxxxxxxxxxxxx 先执行 git fetch 命令&#xff0c;再push。 git拉取远程所有分支/添加远程仓库_git pull所有分支代码-CSDN博客…

OpenGL-ES 学习(8) ---- FBO

目录 FBO OverViewFBO 优点使用FBO的步骤 FBO OverView FBO(FrameBuffer Object) 指的是帧缓冲对象&#xff0c;实际上是一个可以添加缓冲区容器&#xff0c;可以为其添加纹理或者渲染缓冲区对象(RBO) FBO(FrameBuffer Object) 本身不能用于渲染&#xff0c;只有添加了纹理或者…

【C++ Primer Plus习题】3.6

问题: 解答: #include <iostream> using namespace std;int main() {float miles 0;float gallons 0;float gallon 0;cout << "请输入驱车里程(单位为英里):";cin >> miles;cout << "请输入使用的汽油量(单位为加仑):";cin &g…

【Three.js基础学习】19.Custom models with Blender

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 前言 blender模型资源:【blender】一个汉堡包-CSDN博客 一、代码 import ./style.css import * as THREE from three import { OrbitControls } from three/examples/jsm/co…

CentOS服务器三级等保加固

1.密码周期: vim /etc/login.defs max_days:90 mindays:2 minlen:8 warnage:72.密码复杂度: vim /etc/pam.d/system-auth &#xff1a; password requisite pam_cracklib.so retry3 difok3 minlen8 lcredit-1 dcredit-1 ucredit-1 ocredit-1 【Ubuntu系统->vim /etc/pam.d/c…

【STM32】C语言基础补充

学习过程中发现自己好些需要用到的C语言语法、特征都不太熟练了&#xff0c;特意记录一下&#xff0c;免得忘记了&#xff0c;以后遇到了新的也会继续更新 目录 1 全局变量 2 结构体 3 静态变量 4 memset()函数 5 使用8位的存储器存16位的数 1 全局变量…

C++学习笔记----4、用C++进行程序设计(四)---- 复合关系与继承关系之间的细线

在现实世界只是很容易区分对象之间是复合关系还是继承关系。没有人会说桔子有一个水果--而只能是桔子是一种水果。但是&#xff0c;在代码中&#xff0c;有时候就不是那么清晰了。 设想有一个代表关联数组的假想类&#xff0c;将一个键影射到一个值的数据结构。例如&#xff0c…

【Canvas与艺术】环形橄榄枝纹饰

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>环形橄榄枝(draft2)</title><style type"text/css&quo…

MySql 高阶二(SQL 性能分析)

SQL 性能分析&#xff1a; 查看当前数据库的 增删改查的使用情况 show global status like Com_______;慢查询日志&#xff1a; -- 查看状态 show variables like slow_query_log目前是开启状态。如何开启&#xff0c;编辑my.cnf 文件 添加下面的语句&#xff0c;编辑完成后…

Ansible远程自动化运维

目录 概念 安装ansible modules模块和语法 命令行语法 模块 1. command 基础模块 常用的参数 2. shell模块 3. cron定时任务模块 4. user用户管理模块 参数 5. copy复制模块 参数 6. file模块 设置文件属性 参数 实验&#xff1a;批量创建目录 7…

设备实时数据采集:开启制造业智能化、自动化的新篇章

传统制造业在进行生产过程中&#xff0c;会涉及到设备实时数据采集需求&#xff0c;这些数据对于监控生产流程、优化生产效率、保证产品质量以及降低成本等方面至关重要。以下是一些常见的数据采集需求&#xff1a; 1.生产数据&#xff1a;包括生产数量、生产批次、生产速度等&…

如何禁止编辑PDF文件?推荐两种方法!

在日常工作中&#xff0c;我们经常会遇到需要分享重要的PDF文件的情况&#xff0c;但又希望文件内容不被随意更改。为此&#xff0c;设置PDF文件的修改限制是一个非常有效的措施。今天分享两种常见的禁止修改PDF的方法&#xff0c;一起来看看如何设置。 方法一&#xff1a;使用…

FPGA开发——DS18B20读取温度并且在数码管上显示

一、简介 在上一篇文章中我们对于DS18B20的相关理论进行了详细的解释&#xff0c;同时也对怎样使用DS18B20进行了一个简单的叙述。在这篇文章我们通过工程来实现DS18B20的温度读取并且实现在数码管伤显示。 1、基本实现思路 根据不同时刻的操作&#xff0c;我们可以使用一个状…

TCP与UDP传输的学习

void *memset(void *s, int c, size_t n); 功能&#xff1a;将一块内存空间的每个字节都设置为指定的值&#xff1b;这个函数通常用于初始化一个内存空间&#xff0c;或者清空一个空间&#xff1b; 参数&#xff1a;viod * s 空类型指针&#xff0c;指向要填充内存块&#xf…

代码随想录训练营 Day37打卡 动态规划 part05 完全背包理论基础 518. 零钱兑换II 377. 组合总和 Ⅳ 卡码70. 爬楼梯(进阶版)

代码随想录训练营 Day37打卡 动态规划 part05 一、完全背包理论基础 有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品都有无限个&#xff08;也就是可以放入背包多次&#xff09;&#xff0c;求解将哪些物品装…

Arco Design,字节跳动出品的UI库

Arco Design是字节跳动出品的UI库&#xff0c;支持Vue和React。还是比较美观的。并且Arco Design还提供了中后台模版。但是通过提供的arco-cli连接了github&#xff0c;正常情况下无法构建。但效果还是挺好的&#xff0c;下面是效果图&#xff1a; 更新&#xff1a; 传送门可…

【C++ Primer Plus习题】2.3

问题: 解答: #include <iostream> using namespace std;void print01() {cout << "三只眼瞎的老鼠" << endl; }void print02() {cout << "看他们怎么跑" << endl; }int main() {print01();print01();print02();print02();r…

Linux:Linux多线程

目录 线程概念 什么是线程 二级页表 线程的优点 线程的缺点 线程异常 线程用途 Linux进程VS线程 进程和线程 进程的多个线程共享 进程和线程的关系 Linux线程控制 POSIX线程库 线程创建 线程等待 线程终止 分离线程 线程ID及进程地址空间布局 线程概念 什么…