1pipe管道

简介:  1进程间通信 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不 到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用 户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程 间通信(IPC,InterProcess Communication)。 2pip


1进程间通信

每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不

到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用

户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程

间通信(IPCInterProcess Communication)。


2pipe管道

管道是一种最基本的IPC机制,由pipe函数创建:

#include <unistd.h>

int pipe(int filedes[2]);

调用pipe函数时在内核中开辟一块缓冲区(称为管道)用于通信,它有一个读端一个

写端,然后通过filedes参数传出给用户程序两个文件描述符,filedes[0]指向管道的读

端,filedes[1]指向管道的写端(很好记,就像0是标准输入1是标准输出一样)。所以管道

在用户程序看起来就像一个打开的文件,通过read(filedes[0]);或者write(filedes[1]);

向这个文件读写数据其实是在读写内核缓冲区。pipe函数调用成功返回0,调用失败返

-1

   开辟了管道之后如何实现两个进程间的通信呢?比如可以按下面的步骤通信。

1.父进程调用pipe开辟管道,得到两个文件描述符指向管道的两端。

2.父进程调用fork创建子进程,那么子进程也有两个文件描述符指向同一管道。

3.父进程关闭管道读端,子进程关闭管道写端。父进程可以往管道里写,子进程可以从

管道里读,管道是用环形队列实现的,数据从写端流入从读端流出,这样就实现了进程间通

信。

 

关于管道的图

案例1

#include <sys/types.h>

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <stdlib.h>

#include <fcntl.h>

#include <errno.h>

#include <wait.h>

 

int main(void)

{

   int fd[2];

   char str[1024] = "hello toto";

   char buf[1024];

   pid_t pid;

   //fd[0]读端

   //fd[1]写端

   if (pipe(fd) < 0) {

       perror("pipe");

       exit(1);

   }

   pid = fork();

   //父写子读

   if (pid > 0) {

       //父进程里,关闭父读

       close(fd[0]);

       sleep(5);

                  //这里说明fd[1]是写端,strlen表示的是写的长度

       write(fd[1], str, strlen(str));

                  //写完之后要把文件描述符关闭,不然会出现内存泄漏

       close(fd[1]);

       wait(NULL);

   }

   else if (pid == 0) {

       int len, flags;

       //子进程里,关闭子写

       close(fd[1]);

 

       flags = fcntl(fd[0], F_GETFL);

                  //表示fd[0]具有非阻塞属性

       flags |= O_NONBLOCK;

       fcntl(fd[0], F_SETFL, flags);

tryagain:

       len = read(fd[0], buf, sizeof(buf));

       if (len == -1) {

           if (errno == EAGAIN) {

                              //这里的是10"tryagain\n"的长度

               write(STDOUT_FILENO, "tryagain\n", 10);

               sleep(1);

               goto tryagain;

           }

           else {

               perror("read");

               exit(1);

           }

       }

                  //这里表示向屏幕中打印除结果

       write(STDOUT_FILENO, buf, len);

       close(fd[0]);

   }

   else {

       perror("fork");

       exit(1);

   }

   return 0;

}

案例2

运行结果:

总结:通过pipe函数实现两个文件描述符之间的关联

 

使用管道有一些限制:

两个进程通过一个管道只能实现单向通信,比如上面的例子,父进程写子进程读,如果

有时候也需要子进程写父进程读,就必须另开一个管道。请读者思考,如果只开一个管道,

但是父进程不关闭读端,子进程也不关闭写端,双方都有读端和写端,为什么不能实现双向

通信?

管道的读写端通过打开的文件描述符来传递,因此要通信的两个进程必须从它们的公共

祖先那里继承管道文件描述符。上面的例子是父进程把文件描述符传给子进程之后父子进程

之间通信,也可以父进程fork两次,把文件描述符传给两个子进程,然后两个子进程之间通

信,总之需要通过fork传递文件描述符使两个进程都能访问同一管道,它们才能通信。

使用管道需要注意以下4种特殊情况(假设都是阻塞I/O操作,没有设置O_NONBLOCK

志):

1.如果所有指向管道写端的文件描述符都关闭了(管道写端的引用计数等于0),而仍

然有进程从管道的读端读数据,那么管道中剩余的数据都被读取后,再次read会返回0,就

像读到文件末尾一样。

2.如果有指向管道写端的文件描述符没关闭(管道写端的引用计数大于0),而持有管

道写端的进程也没有向管道中写数据,这时有进程从管道读端读数据,那么管道中剩余的数

据都被读取后,再次read会阻塞,直到管道中有数据可读了才读取数据并返回。

3.如果所有指向管道读端的文件描述符都关闭了(管道读端的引用计数等于0),这时

有进程向管道的写端write,那么该进程会收到信号SIGPIPE,通常会导致进程异常终止。

在第33章信号会讲到怎样使SIGPIPE信号不终止进程。

4.如果有指向管道读端的文件描述符没关闭(管道读端的引用计数大于0),而持有管

道读端的进程也没有从管道中读数据,这时有进程向管道写端写数据,那么在管道被写满时

再次write会阻塞,直到管道中有空位置了才写入数据并返回。

管道的这四种特殊情况具有普遍意义。

 


 

 

 

 

 

 


目录
相关文章
|
Cloud Native Serverless 容器
袋鼠:云原生底层系统探索和实践
随着云计算的发展,云原生概念已经开始成为一种被广泛接受的开发理念。本文将概述我们面向云原生场景在底层技术方面做的探索以及实践。文章根据云栖大会系统软件专场内容整理,演讲者:韩伟东
4268 1
|
数据库 Perl
分享几本 O'Reilly 出品的免费电子书
有一些书,如果你不是行内人士,那么可能你一辈子都不会看。有一些出版社,就是专门做这种书,比如国内的机工华章,比如国外的 O'Reilly,都是专注计算机和软件行业二十年的好出版社。 这两家出版社的书,都是颇有特色个性鲜明。华章的图书,我在大学期间读了很多,以计算机科学领域的基础和经典居多,这套书在
12483 0
|
7月前
|
Java
java引入本地 MultipartFile 实现多部分文件上传
在Java中,`MultipartFile`通常用于处理通过HTML表单上传的文件。但在某些情况下,需要直接从本地文件系统获取文件并上传。本文介绍如何创建一个实现了`MultipartFile`接口的本地类`LocalMultipartFile`,将本地文件转换为`MultipartFile`对象,简化文件上传流程。此方法适用于批量上传等场景,避免了表单上传的复杂性。代码示例展示了如何实现和使用该类进行文件上传操作。作者:华科云商小彭。链接:[稀土掘金](https://juejin.cn/post/7377559533785530431)。
321 18
|
9月前
|
人工智能 数据挖掘 大数据
Freestyler:微软联合西工大和香港大学推出说唱音乐生成模型,支持控制生成的音色、风格和节奏等
Freestyler是由西北工业大学、微软和香港大学联合推出的说唱乐生成模型,能够根据歌词和伴奏直接生成说唱音乐。该模型基于语言模型生成语义标记,并通过条件流匹配模型和神经声码器生成高质量音频。Freestyler还推出了RapBank数据集,支持零样本音色控制和多种应用场景。
299 16
Freestyler:微软联合西工大和香港大学推出说唱音乐生成模型,支持控制生成的音色、风格和节奏等
|
9月前
|
机器学习/深度学习 人工智能 编解码
OminiControl:AI图像生成框架,实现图像主题控制和空间精确控制
OminiControl 是一个高度通用且参数高效的 AI 图像生成框架,专为扩散变换器模型设计,能够实现图像主题控制和空间精确控制。该框架通过引入极少量的额外参数(0.1%),支持主题驱动控制和空间对齐控制,适用于多种图像生成任务。
234 10
OminiControl:AI图像生成框架,实现图像主题控制和空间精确控制
|
9月前
|
索引 搜索推荐 UED
基于elasticsearch + huggingface model 实现语义检索
项目地址:https://github.com/skyterra/elastic-embedding-searcher。本项目利用Hugging Face模型生成文本的嵌入向量,并将其同步至Elasticsearch创建索引,支持通过余弦相似度进行高效的向量搜索,实现精准的内容检索与推荐功能。该项目为开发智能搜索应用提供了强大的后端支持。 (该简介有239个字符,包括标点和空格)
287 8
|
8月前
|
存储 架构师 容灾
阿里云基础设施高可用最佳实践沙龙上海站圆满举办!
2025年1月9日,阿里云在上海虹桥绿地铂瑞酒店成功举办基础设施高可用最佳实践沙龙NO.1。活动吸引了华东地区多家企业的CTO、架构师和技术从业者参与。专家们分享了高可用的基础知识、分级标准及云端架构实战经验,涵盖计算、存储、网络和云原生等领域,重点讨论了企业如何在阿里云上构建高可用数据中心。现场互动热烈,参会者与专家深入交流,探讨技术应用与合作机会。
|
机器学习/深度学习 Shell C++
测试本地部署ChatGLM-6B | ChatGPT
ChatGLM-6B是款62亿参数的中英对话模型,类似ChatGPT,可在6GB显存(INT4量化)的GPU或CPU上运行。它提供流畅、多样的对话体验。用户可从Hugging Face或清华云下载模型配置。部署涉及创建Python环境,安装依赖,下载模型到`ckpt`文件夹。测试时加载tokenizer和模型,使用示例代码进行交互。应用包括基于MNN和JittorLLMs的推理实现,以及langchain-ChatGLM、闻达、chatgpt_academic和glm-bot等项目。5月更文挑战第10天
329 1
|
存储 cobar 关系型数据库
MyCat-简介-MyCat 历史 | 学习笔记
快速学习 MyCat-简介-MyCat 历史
MyCat-简介-MyCat 历史 | 学习笔记
|
负载均衡 中间件 应用服务中间件
Nginx动静分离详解以及配置
1.Nginx动静分离概念 动静分离,通过中间件将动态请求和静态请求进行分离,分离资源,减少不必要的请求消耗,减少请求延时。 好处:动静分离后,即使动态服务不可用,但静态资源不会受到影响 通过中间件可以将动态请求和静态请求进行分离
552 0
Nginx动静分离详解以及配置