当前位置: 首页 > news >正文

进程间通信(管道)

进程间通信博客整理

进程间通信的重要性

在操作系统中,进程是资源分配和调度的基本单位。每个进程都拥有自己独立的地址空间和资源,这使得进程之间不能直接访问彼此的内存或资源。然而,在实际应用中,不同进程之间往往需要进行数据交换或协作,这就是进程间通信(Inter-Process Communication, IPC)的重要性所在。

进程间通信的方式
环境变量

环境变量是一种简单的进程间通信方式,但它只适用于显式拷贝的情况,并不能实现真正的进程间动态通信。

公共资源

为了实现进程间的通信,操作系统可以创建一些公共资源,如共享内存、消息队列、管道等,供不同进程使用。

本地通信

在同一台主机、同一操作系统下,不同进程之间的通信称为本地通信。System V通信标准是其中的一种通信标准。

进程间通信分类
  • 管道:通过文件在内存中的共享来实现通信。
  • 共享内存:允许多个进程访问同一块内存区域。
  • 消息队列:以消息为单位进行通信。
  • 信号量:用于控制进程对共享资源的访问。
  • 套接字:用于网络通信,但也可以用于本地进程间通信。
管道通信

管道是一种古老而经典的进程间通信方式。

  • 原理:当子进程和父进程包含同一文件时,此文件在内存中只有一份副本。父子进程通过该文件进行通信。虽然父子进程的struct file结构体是独立的(读写位置不同),但内存中的inode和内核级缓冲区是共享的。
  • 特点:管道通信文件是内存级的,不需要刷新到磁盘。这种管道没有名字,也称为匿名管道。
  • 限制:管道只能单向通信。为了实现双向通信,需要创建两个管道。
管道的四现象
  1. 管道为空且管道正常:此时,读操作会阻塞,直到有数据写入管道。
  2. 管道为满且管道正常:此时,写操作会阻塞,直到有数据从管道中读出。
  3. 写端关闭且读端继续:此时,读操作会读到文件结束符(EOF),表示管道已空。
  4. 写端继续且读端关闭:此时,操作系统会向写入进程发送信号(如SIGPIPE,信号编号13),通常导致写入进程异常终止。
匿名管道的特性
  • 管道内容大小有上限:通常为65536字节(或称为64KB)。
  • 生命周期:管道的生存周期与创建它的进程相关。当所有使用管道的进程都终止时,管道也会被销毁。
  • 单向性:如上所述,匿名管道只能单向通信。为了实现双向通信,需要创建两个管道或使用其他通信方式。
代码示例
#include <iostream>
#include <string>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>// Fater process -> read
// Child process -> write
int main()
{// 1. 创建管道int fds[2] = {0};int n = pipe(fds); // fds:输出型参数if (n != 0){std::cerr << "pipe error" << std::endl;return 1;}// Fater process -> read// Child process -> write// 2. 创建子进程pid_t id = fork();if (id < 0){std::cerr << "fork error" << std::endl;return 2;}else if (id == 0){// 子进程// 3. 关闭不需要的fd,关闭readclose(fds[0]);int cnt = 0;int total = 0;while (true){std::string message = "h";// message += std::to_string(getpid());// message += ", ";// message += std::to_string(cnt);// fds[1]total += ::write(fds[1], message.c_str(), message.size());cnt++;std::cout << "total: " << total << std::endl;sleep(2);// break;}exit(0);}else{// 父进程// 3. 关闭不需要的fd,关闭writeclose(fds[1]);char buffer[1024];while (true){sleep(1);ssize_t n = ::read(fds[0], buffer, 1024);if (n > 0){buffer[n] = 0;std::cout << "child->father, message: " << buffer << std::endl;}else if(n == 0) {// 如果写端关闭// 读端读完管道内部的数据,在读取的时候,// 就会读取到返回值0,表示对端关闭,也表示读到文件结尾std::cout << "n:" << n << std::endl;std::cout << "child quit ??? me too" << std::endl;break;}close(fds[0]);break;std::cout << std::endl;}int status = 0;pid_t rid = waitpid(id, &status, 0);std::cout << "father wait child success: " << rid << " exit code: " <<((status<<8)&0xFF) << ", exit sig: " << (status & 0x7F) << std::endl;}return 0;
}

板书笔记


http://www.mrgr.cn/news/60002.html

相关文章:

  • (二十二)Java网络编程
  • 前端处理API接口故障:多接口自动切换的实现方案
  • ATmega128定时器里面的定时器和外部中断配置
  • C#判断带数字的字符串数组连续性的两种方式
  • Linux操作系统安全加固
  • Zig 语言通用代码生成器:逻辑,冒烟测试版发布二
  • 【已解决,含泪总结】非root权限在服务器上配置python和torch环境,代码最终成功训练(一)
  • Ubuntu22.04编译安装实时内核
  • 2-135 基于matlab的有限差分法计算电位分布
  • 1025. 除数博弈
  • maven之pom.xml文件解读
  • flink1.17.2安装和使用
  • 基于协同过滤算法的旅游网站推荐系统
  • iTerm2 保持SSH远程连接
  • PyQt入门指南二十九 QListView列表视图组件
  • leetcode day7 442
  • 揭秘:如何用Puppeteer和BrowserWS解锁网站性能的隐秘角落
  • 【CTF】 文件包含漏洞——data伪协议 【详】
  • python之多任务爬虫——线程、进程、协程的介绍与使用(16)
  • C++20新特性探索:概念(Concepts)与范围库(Ranges)
  • 特定机器学习问题的基准测试数据
  • 【Vue3】第二篇
  • 15-5小C的外卖超时判断
  • 单例模式 — 设计模式
  • 【工程】mmcls中EfficientNet网络转onnx格式问题记录
  • 最近阶段的状态的复盘