12.1 Linux_进程间通信_管道

news/2024/10/6 15:39:10/

概述

什么是无名管道:

无名管道就是在内核中开辟了一块内存,进程1和进程2都可以访问这一块空间,从而实现通信。

当无名管道被创建时,父进程fd[0]指向管道的读端,fd[1]指向管道的写端。fork创建子进程后,子进程也有一对fd[0]指向管道的读端,fd[1]指向管道的写端。具体结构如下:

之后可以使一个进程关闭读端,另一个进程关闭写端。关闭后的具体结构如下: 

无名管道(pipe)的特点:

  • 只能用作父子进程、兄弟进程之间的通信。
  • 单工通信,具有固定的读端和写端。即:只能一段读一段写,如果想读写都可以,则需要两条管道。
  • 创建无名管道时会返回2个文件描述符,分别用于读写管道

有名管道(fifo)的特点:

  • 解决了无名管道只能用作父子进程、兄弟进程之间的通信的问题
  • 有名管道通过路径名操作(管道文件p),在文件系统中可见,但内容存放在内存中。
  • 遵循先进先出规则。
  • 不支持lseek操作光标位置。
  • 单工通信。

无名管道

1、创建

int pipe(int pipefd[2]);

返回值:成功返回0,失败返回EOF

pipefd:返回的文件描述符,pipefd[0]用于读,pipefd[1]用于写

注意:对于一个进程,只能使用一个文件描述符。即:该进程要么读管道,要么写管道,不能同时读写。

2、读写

读写管道就是使用文件I/O,像普通文件一样进行读写。

读管道特性:

  • 管道中有数据,read返回实际读取到的字节数
  • 管道中无数据,且写端全部关闭,read返回0
  • 管道中无数据,但写端没有关闭,read阻塞等待

写管道特性:

  • 写管道时,读端全部关闭,进程异常终止,信号为SIGPIPE(管道破裂)。
  • 写管道时,如果管道已满,write阻塞等待。管道大小为64K
  • 写管道时,如果管道未满,write返回实际写入的字节数

实验代码 

无名管道实验代码如下:

#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>int main(){int pfd[2];pid_t pid;char buf[100] = {0};//创建无名管道if(pipe(pfd)<0){perror("pipe");return -1;}pid = fork();if(pid<0){perror("fork");return -1;}else if(pid == 0){while(1){write(pfd[1],"pipe test",strlen("pipe test"));//写管道close(pfd[0]);//关闭读sleep(1);}}else{while(1){read(pfd[0],buf,sizeof(buf));//读管道close(pfd[1]);//关闭写printf("read:%s\n",buf);}}return 0;
}

有名管道

1、创建

int mkfifo(const char *pathname, mode_t mode);

返回值:成功返回0,失败返回EOF 

pathname:文件路径,不要新建在共享目录下。

mode:文件权限,实际权限 = mode & (~umask) 

2、打开

打开管道文件就是使用使用文件I/O的open函数。

注意:open的flag参数只能传入O_RDONLY或O_WRONLY,因为管道只能一端读或一端写。

注意:当open的flag没有加上O_NONBLOCK时,open进入阻塞状态,直到有另一个进程以对应的只读或只写打开。即:进程A只读打开时阻塞,直到进程B只写打开;或者进程A只写打开时阻塞,直到进程B只读打开。

3、读写

读写管道就是使用文件I/O,像普通文件一样进行读写。

写入数据完整性问题:

在多进程写入管道时,当写入数据的大小 <= PIPE_BUF(4K)时,系统会自动保证数据的完整性,即要么全部写入,要么一个不写。当写入数据 > 4K时,不能自动保证数据完整性。

实验代码

writefifo.c代码如下:

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>#define FIFO_PATH "./fifo"
int main(){int fd;//创建有名管道if(mkfifo(FIFO_PATH,0777)<0){perror("mkfifo");}//打开管道文件if((fd = open(FIFO_PATH,O_WRONLY)) < 0){//以只读方式打开perror("open");}//写管道while(1){write(fd,"write fifo",strlen("write fifo"));printf("has write\n");sleep(1);}//关闭文件close(fd);return 0;
}

readfifo.c代码如下:

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>#define FIFO_PATH "./fifo"
int main(){int fd;char buf[100];//打开管道文件if((fd = open(FIFO_PATH,O_RDONLY)) < 0){//以只写方式打开perror("open");}//读管道while(1){//有数据才操作,防止写端关闭read不进行阻塞导致刷屏if(read(fd,buf,sizeof(buf)-1)>0){printf("read:%s\n",buf);memset(buf,0,sizeof(buf));}}//关闭文件close(fd);return 0;
}

代码运行结果如下:


http://www.ppmy.cn/news/1535390.html

相关文章

Unity 编辑器多开

开发多人联机的功能时大多数会遇到测试机不方便的问题。想多开同一个项目Uinty又禁止。。。因为在使用Unity Editor打开一个项目时&#xff0c;Unity Editor会在项目目录建立一个Temp目录&#xff0c;同时对里面的一个UnityLockfile文件进行加锁。SO...可以使用以下方法进行多开…

行为设计模式 -模板方法模式- JAVA

模板方法模式 一 .简介二. 案例2.1 抽象类&#xff08;Abstract Class&#xff09;2.2 具体子类&#xff08;Concrete Class&#xff09;2.3 测试 三. 结论3.1 优缺点3.2 适用场景3.3 要点 前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接…

影刀RPA实战:Excel密码与字典功能指令

1.实战目标 本次主要讲解下影刀RPA操作Excel密码保护和数据列生成字典&#xff0c;在工作中&#xff0c;我们经常会遇到合作公司给我们发的表格&#xff0c;或是电商平台下载订单Excel数据表都带有密码&#xff0c;这在自动化处理过程中&#xff0c;多少带来不变&#xff0c;影…

使用keras-tuner微调神经网络超参数

目录 随机搜索RandomSearch HyperBand 贝叶斯优化BayesianOptimization 附录 本文将介绍keras-tuner提供了三种神经网络超参数调优方法。它们分别是随机搜索RandomSearch、HyperBand和贝叶斯优化BayesianOptimization。 首先需要安装keras-tuner依赖库,安装命令如…

第二十讲-布局管理QFormLayout

QFormLayout 是 PyQt5 中的一种布局管理器,专门用于排列表单(form)风格的小部件。它可以方便地将标签和输入控件以 "标签-控件" 的方式进行垂直排列,使界面看起来更简洁有序。通常用于创建如登录界面、设置窗口等表单界面。 初步示例 下面是一个简单的示例,展…

58 深层循环神经网络_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录深度循环神经网络1. 模型复杂性增加2. 训练数据不足3. 梯度消失和爆炸4. 正则化不足5. 特征冗余总结 函数依赖关系简洁实现训练与预测小结练习 深度循环神经网络 &#x1f3f7;sec_deep_rnn 到目前为止&#xff0c;我们只讨论了具有一个单…

GWAS分析中显著位点如何注释基因:excel???

大家好&#xff0c;我是邓飞。 今天星球的小伙伴问了一个问题&#xff1a; 我现在在做GWAS分析&#xff0c;现在已经找到性状关联的SNP位点&#xff0c;下一步我如何根据position 找到基因呢&#xff1f; 关于基因注释&#xff0c;之前写过一些博客&#xff0c;可以用到的软件…

vue页面保持在div的底部(适用于聊天界面等需要显示最新信息的场景)

代码示例&#xff1a; <script setup lang"ts"> import {nextTick, onMounted, ref} from vueconst count [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, …