【在Linux世界中追寻伟大的One Piece】进程间通信
目录
1 -> 进程间通信介绍
1.1 -> 进程间通信目的
1.2 -> 进程间通信发展
1.3 -> 进程间通信分类
1.3.1 -> 管道
1.3.2 -> System V IPC
1.3.3 -> POSIX IPC
2 -> 管道
2.1 -> 什么是管道
2.2 -> 匿名管道
2.3 -> 实例代码
2.4 -> 用fork来共享管道原理
2.5 -> 站在文件描述符角度——深度理解管道
2.6 -> 站在内核角度——管道本质
3 -> 管道读写规则
4 -> 管道特点
1 -> 进程间通信介绍
1.1 -> 进程间通信目的
- 数据传输:一个进程需要将它的数据发送给另一个进程。
- 资源共享:多个进程之间共享同样的资源。
- 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
- 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。
1.2 -> 进程间通信发展
- 管道
- System V进程间通信
- POSIX进程间通信
1.3 -> 进程间通信分类
1.3.1 -> 管道
- 匿名管道pipe
- 命名管道
1.3.2 -> System V IPC
- System V消息队列
- System V共享内存
- System V信号量
1.3.3 -> POSIX IPC
- 消息队列
- 共享内存
- 信号量
- 互斥量
- 条件变量
- 读写锁
2 -> 管道
2.1 -> 什么是管道
- 管道是Unix中最古老的进程间通信的形式。
- 我们把从一个进程连接到另一个进程的一个数据流称为一个"管道"。
2.2 -> 匿名管道
#include <unistd.h>功能:创建一无名管道原型int pipe(int fd[2]);参数fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端返回值:成功返回0,失败返回错误代码
2.3 -> 实例代码
#define _CRT_SECURE_NO_WARNINGS 1//例子:从键盘读取数据,写入管道,读取管道,写到屏幕
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>int main(void)
{int fds[2];char buf[100];int len;if (pipe(fds) == -1)perror("make pipe"), exit(1);// read from stdinwhile (fgets(buf, 100, stdin)) {len = strlen(buf);// write into pipeif (write(fds[1], buf, len) != len) {perror("write to pipe");break;}memset(buf, 0x00, sizeof(buf));// read from pipeif ((len = read(fds[0], buf, 100)) == -1) {perror("read from pipe");break;}// write to stdoutif (write(1, buf, len) != len) {perror("write to stdout");break;}}
}
2.4 -> 用fork来共享管道原理
2.5 -> 站在文件描述符角度——深度理解管道
2.6 -> 站在内核角度——管道本质
所以,看待管道,就如同看待文件一样!管道的使用和文件一致,迎合了"Linux一切皆文件思想"。
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>#define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE); \ } while(0)
int main(int argc, char* argv[])
{int pipefd[2]; if (pipe(pipefd) == -1) ERR_EXIT("pipe error");pid_t pid;pid = fork();if (pid == -1)ERR_EXIT("fork error");if (pid == 0) {close(pipefd[0]);write(pipefd[1], "hello", 5);close(pipefd[1]);exit(EXIT_SUCCESS);}close(pipefd[1]);char buf[10] = { 0 };read(pipefd[0], buf, 10);printf("buf=%s\n", buf);return 0;
}
例1. 在minishell中添加管道的实现:
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <string.h>
# include <fcntl.h># define MAX_CMD 1024char command[MAX_CMD];int do_face()
{memset(command, 0x00, MAX_CMD);printf("minishell$ ");fflush(stdout);if (scanf("%[^\n]%*c", command) == 0) {getchar();return -1;}return 0;
}char** do_parse(char* buff)
{int argc = 0;static char* argv[32];char* ptr = buff;while (*ptr != '\0') {if (!isspace(*ptr)) {argv[argc++] = ptr;while ((!isspace(*ptr)) && (*ptr) != '\0') {ptr++;}}else {while (isspace(*ptr)) {*ptr = '\0';ptr++;}}}argv[argc] = NULL;return argv;
}int do_redirect(char* buff)
{char* ptr = buff, * file = NULL;int type = 0, fd, redirect_type = -1;while (*ptr != '\0') {if (*ptr == '>') {*ptr++ = '\0';redirect_type++;if (*ptr == '>') {*ptr++ = '\0';redirect_type++;}while (isspace(*ptr)) {ptr++;}file = ptr;while ((!isspace(*ptr)) && *ptr != '\0') {ptr++;}*ptr = '\0';if (redirect_type == 0) {fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0664);}else {fd = open(file, O_CREAT | O_APPEND | O_WRONLY, 0664);}dup2(fd, 1);}ptr++;}return 0;
}int do_command(char* buff)
{int pipe_num = 0, i;char* ptr = buff;int pipefd[32][2] = { {-1} };int pid = -1;pipe_command[pipe_num] = ptr;while (*ptr != '\0') {if (*ptr == '|') {pipe_num++;*ptr++ = '\0';pipe_command[pipe_num] = ptr;continue;}ptr++;}pipe_command[pipe_num + 1] = NULL;return pipe_num;
}int do_pipe(int pipe_num)
{int pid = 0, i;int pipefd[10][2] = { {0} };char** argv = { NULL };for (i = 0; i <= pipe_num; i++) {pipe(pipefd[i]);}for (i = 0; i <= pipe_num; i++) {pid = fork();if (pid == 0) {do_redirect(pipe_command[i]);argv = do_parse(pipe_command[i]);if (i != 0) {close(pipefd[i][1]);dup2(pipefd[i][0], 0);}if (i != pipe_num) {close(pipefd[i + 1][0]);dup2(pipefd[i + 1][1], 1);}execvp(argv[0], argv);}else {close(pipefd[i][0]);close(pipefd[i][1]);waitpid(pid, NULL, 0);}}return 0;
}int main(int argc, char* argv[])
{int num = 0;while (1) {if (do_face() < 0)continue;num = do_command(command);do_pipe(num);}return 0;
}
3 -> 管道读写规则
- 当没有数据可读时:
- O_NONBLOCK disable:read调用阻塞,即进程暂停执行,一直等到有数据来到为止。
- O_NONBLOCK enable:read调用返回-1,errno值为EAGAIN。
- 当管道满的时候:
- O_NONBLOCK disable: write调用阻塞,直到有进程读走数据。
- O_NONBLOCK enable:调用返回-1,errno值为EAGAIN。
- 如果所有管道写端对应的文件描述符被关闭,则read返回0。
- 如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGPIPE,进而可能导致write进程退出。
- 当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。
- 当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。
4 -> 管道特点
- 只能用于具有共同祖先的进程(具有亲缘关系的进程)之间进行通信;通常,一个管道由一个进程创建,然后该进程调用fork,此后父、子进程之间就可应用该管道。
- 管道提供流式服务。
- 一般而言,进程退出,管道释放,所以管道的生命周期随进程。
- 一般而言,内核会对管道操作进行同步与互斥。
- 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道。
感谢各位大佬支持!!!
互三啦!!!
相关文章:

【在Linux世界中追寻伟大的One Piece】进程间通信
目录 1 -> 进程间通信介绍 1.1 -> 进程间通信目的 1.2 -> 进程间通信发展 1.3 -> 进程间通信分类 1.3.1 -> 管道 1.3.2 -> System V IPC 1.3.3 -> POSIX IPC 2 -> 管道 2.1 -> 什么是管道 2.2 -> 匿名管道 2.3 -> 实例代码 2.4 -…...

多路复用IO
一。进程处理多路IO请求 在没有多路复用IO之前,对于多路IO请求,一般只有阻塞与非阻塞IO两种方式 1.1 阻塞IO 需要结合多进程/多线程,每个进程/线程处理一路IO 缺点:客户端越多,需要创建的进程/线程越多,…...

C++ prime plus-7-編程練習
1, #include <iostream>// 函数声明 double harmonicMean(double x, double y);int main() {double x, y, result;while (true) {std::cout << "请输入两个数(其中一个为0时结束): ";std::cin >> x >> y;…...

计算1 / 1 - 1 / 2 + 1 / 3 - 1 / 4 + 1 / 5 …… + 1 / 99 - 1 / 100 的值,打印出结果
我们写这道题的时候需要俩变量接受,一个总数一个分母,我们发现分母变化是有规律的从1~100循环。 #include<stdio.h> int main() {int i 0;int tag 1;double sum 0.0;for (i 1; i < 101; i){if (i % 2 0){sum sum - 1.0 / i;}else{sum s…...

Linux本地服务器搭建开源监控服务Uptime Kuma与远程监控实战教程
文章目录 前言**主要功能**一、前期准备本教程环境为:Centos7,可以跑Docker的系统都可以使用本教程安装。本教程使用Docker部署服务,如何安装Docker详见: 二、Docker部署Uptime Kuma三、实现公网查看网站监控四、使用固定公网地址…...

JS 历史简介
目录 1. JS 历史简介 2. JS 技术特征 1. JS 历史简介 举例:在提交用户的注册信息的时候,为避免注册出现错误后重新填写信息,可以在写完一栏信息后进行校验,并提示是否出现错误,这样会大大提高用户提交的成功率&…...

爬虫逆向学习(七):补环境动态生成某数四代后缀MmEwMD
声明:本篇文章内容是整理并分享在学习网上各位大佬的优秀知识后的实战与踩坑记录 前言 这篇文章主要是研究如何动态生成后缀参数MmEwMD的,它是在文章爬虫逆向学习(六):补环境过某数四代的基础上进行研究的,代码也是在它基础上增…...

光伏电站并网验收需要注意什么细节
一、设备质量及安装验收 光伏组件:检查光伏组件的外观是否完好无损,无明显的缺陷和破损,表面是否清洁无污染。同时,需要验证光伏组件的型号、参数是否与设备台账资料一致。 逆变器:确认逆变器具备防雷、防尘、防潮等…...

页面禁用鼠标右键属于反爬虫措施吗 ?
是的,禁用鼠标右键通常被视为一种反爬虫(anti-scraping)措施。网站开发者常常采用这种技术来防止用户通过右键菜单复制文本、图像或其他内容,特别是在内容保护和数据安全方面。以下是禁用鼠标右键的一些背景和目的: 1…...

视频理解大模型最新进展
文章目录 Video-LLaMAVision-Language BranchAudio-Language Branch Video-ChatGPTMiniGPT4-videoCogVLM2-Video(1)Pre-training(2)Post-training Qwen2-VLMA-LMMChat-UniVi大模型对比 Video-LLaMA 2023:阿里达摩院的…...

cocos creator 使用 protobuf 的步骤与注意事项
移除可能曾安装过的protobuf // 移除全局 npm remove -g protobufjs npm remove -g protobufjs-cli npm remove -g pbjs // 移除项目中的 npm remove --save protobufjs npm remove --save protobufjs-cli npm remove --save pbjs全局安装 npm i -g protobufjs //或者 cnpm …...

mac访达查找文件目录
mac访达查找文件目录 在Mac上使用访达(Finder)查找文件或目录的方法如下: 打开访达。 在访达窗口的侧边栏中,选择“ Go to Folder”(转到文件夹)选项,或者使用快捷键ShiftCommandG打开一个对…...

【数据结构】点分治 点分树
求树上长度小于等于k的路径 #include <iostream> #include <cstring> #include <algorithm>using namespace std;const int N 10010, M N * 2;int n, m; int h[N], e[M], w[M], ne[M], idx; //邻接表 bool st[N]; //记录每个点是否被删掉 int p[N]; //存储…...

K8s Calico替换为Cilium,以及安装Cilium过程(鲁莽版)
迁移CNI插件的3种办法: 1、创建一个新的集群,通过Gitops的方式迁移负载,然而,这可能涉及大量的准备工作和潜在的中断。 2、另一种方法是重新配置/etc/cni/net.d/指向Cilium。但是,现有的pod仍将由旧的…...

背景图鼠标放上去切换图片过渡效果
文章目录 css鼠标放上去之前效果鼠标放上去时效果 css <li class"message"></li>.message {width: 22px;height: 22px;background-image: url(/assets/message-01.png);background-size: cover;background-position: center;transition: background-ima…...

【Linux】当前进展
驱动层日志添加了下文件目录,函数,代码行的打印(这里要小心,驱动目录源代码打印日志里边添进程号可能有问题,因为在驱动初始化的时候,内核还没有创建进程,不过猜测可以先不打印进程相关信息&…...

阿里云云效多个ssh密钥对配置
实现功能 windows本地多个ssh密钥对,分别对应不同的阿里云账号的云效 实现办法 1.生成ssh密钥对 ssh-keygen -t rsa -f C:\xxx\id_rsa_customname(我这里C:\Users\admin\.ssh\id_rsa_customname) 2.配置.ssh目录的config文件 # ruiyi Host customnameHostName codeup.al…...

前后端跨域问题及其在ThinkPHP中的解决方案
在现代Web开发中,前后端分离的架构越来越普遍,但这也带来了跨域问题。跨域指的是在一个域下的网页试图请求另一个域的资源,浏览器出于安全考虑会限制这种行为。本文将探讨如何在ThinkPHP中解决跨域问题。 #### 1. 什么是跨域? 跨…...

基于CentOS7上安装MicroK8s(最小生产的 Kubernetes)
简介 MicroK8s是一个轻量级的Kubernetes发行版,其内存和存储要求远低于全尺寸Kubernetes集群。它可以在几分钟内通过一条命令快速创建功能齐全的Kubernetes集群,极大地简化了部署过程。 兼容性:MicroK8s与Kubernetes全面兼容,确保用户可以无缝迁移和扩展他们的应用程序。 …...

从《GTA5》的反外挂斗争看网络安全的重要性
摘要: 在网络游戏的世界里,外挂(作弊软件)一直是破坏游戏公平性和玩家体验的一大难题。作为一款深受全球玩家喜爱的游戏,《GTA5》(Grand Theft Auto V)在线模式也不例外地遭遇了外挂问题。本文将…...

python如何将字符转换为数字
python中的字符数字之间的转换函数 int(x [,base ]) 将x转换为一个整数 long(x [,base ]) 将x转换为一个长整数 float(x ) 将x转换到一个浮点数 complex(real [,imag ]) 创建一个复数 str(x ) 将对象 x 转换为字…...

TikTok流量不佳:是网络环境选择不当还是其他原因?
TikTok,作为全球短视频社交平台的佼佼者,每天都有海量的内容被上传和分享。然而,很多用户和内容创作者发现,他们的TikTok视频流量并不理想。这引发了一个问题:TikTok流量不佳,是因为网络环境选择不当&#…...

QT菜单栏设计(二级菜单栏)
目的:创建一级菜单栏,添加对应选项,并向一级菜单栏中添加二级菜单栏选项。 #include "mainwindow.h" #include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindo…...

网站建设中,常用的后台技术有哪些,他们分别擅长做什么网站平台
PHP、Python、JavaScript、Ruby、Java和.NET各自适用于不同类型的网站平台。以下是对这些编程语言适用场景的具体介绍: PHP Web开发:PHP是一种广泛使用的开源服务器端脚本语言,特别适合Web开发。全球有超过80%的网站使用PHP作为服务器端编程语…...

【线程】POSIX信号量---基于环形队列的生产消费者模型
信号量概念 这篇文章是以前写的,里面讲了 System V的信号量的概念,POSIX信号量和SystemV信号量作用相同,都是用于同步操作,达到无冲突的访问共享资源目的。 但POSIX可以用于线程间同步。 信号量的概念 POSIX信号量的接口 初始化…...

Excel 设置自动换行
背景 版本:office 专业版 11.0 表格内输入长信息,发现默认状态时未自动换行的,找了很久设置按钮,遂总结成经验帖。 操作 1)选中需设置的单元格/区域/行/列。 2)点击【开始】下【对齐方式】中的【自动换…...

UNI-SOP使用说明
UNI-SOP提供了两个集成客户端:SpringBoot2.x/JAVA1.8和SpringBoot3.x/JAVA17,满足不同项目的集成需求。 平台接入 使用UNI-SOP之前,业务平台需要进行接入,完成校验后才能正常使用,先引入客户端开发SKD包。 <depen…...

记录-java web 生成并下载zip文件
java生成zip文件,zip文件分两种:一种是包含文件夹、一种是不包含文件夹 生成zip文件的方式 ZipOutputStream zipOutputStream new ZipOutputStream(response.getOutputStream());// 文件夹名称String folder "download/";ZipEntry ze new Z…...

大数据集群部署文档
大数据集群部署文档 注意:需配合大数据集群启动&检查文档进行部署,以便可以检验每一个组件是否部署成功。 文章目录 大数据集群部署文档一、部署前准备1. 确保所有机器可以访问外网2. 配置root用户ssh连接3. 解决Vmware ESXi 6.5 Ubuntu虚拟机ssh连…...

HTML中的表单(超详细)
一、表单 1.语法 <!-- action:提交的地方 method:提交的方式(get会显示,post不会) --> <form action"#" method"get"><p>名字:<input name"name" ty…...