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 容器
袋鼠:云原生底层系统探索和实践
随着云计算的发展,云原生概念已经开始成为一种被广泛接受的开发理念。本文将概述我们面向云原生场景在底层技术方面做的探索以及实践。文章根据云栖大会系统软件专场内容整理,演讲者:韩伟东
4547 1
|
存储 SQL 数据库
SQL Server存储过程的优缺点
【10月更文挑战第18天】SQL Server 存储过程具有提高性能、增强安全性、代码复用和易于维护等优点。它可以减少编译时间和网络传输开销,通过权限控制和参数验证提升安全性,支持代码共享和复用,并且便于维护和版本管理。然而,存储过程也存在可移植性差、开发和调试复杂、版本管理问题、性能调优困难和依赖数据库服务器等缺点。使用时需根据具体需求权衡利弊。
300 1
|
12月前
|
人工智能 数据挖掘 大数据
Freestyler:微软联合西工大和香港大学推出说唱音乐生成模型,支持控制生成的音色、风格和节奏等
Freestyler是由西北工业大学、微软和香港大学联合推出的说唱乐生成模型,能够根据歌词和伴奏直接生成说唱音乐。该模型基于语言模型生成语义标记,并通过条件流匹配模型和神经声码器生成高质量音频。Freestyler还推出了RapBank数据集,支持零样本音色控制和多种应用场景。
417 16
Freestyler:微软联合西工大和香港大学推出说唱音乐生成模型,支持控制生成的音色、风格和节奏等
|
12月前
|
机器学习/深度学习 人工智能 编解码
OminiControl:AI图像生成框架,实现图像主题控制和空间精确控制
OminiControl 是一个高度通用且参数高效的 AI 图像生成框架,专为扩散变换器模型设计,能够实现图像主题控制和空间精确控制。该框架通过引入极少量的额外参数(0.1%),支持主题驱动控制和空间对齐控制,适用于多种图像生成任务。
311 10
OminiControl:AI图像生成框架,实现图像主题控制和空间精确控制
|
安全 物联网 物联网安全
揭秘区块链技术在物联网(IoT)安全中的革新应用
揭秘区块链技术在物联网(IoT)安全中的革新应用
|
存储 数据采集 数据安全/隐私保护
商汤、清华、复旦等开源百亿级多模态数据集,可训练类GPT-4o模型
商汤科技、清华大学和复旦大学等机构联合开源了名为OmniCorpus的多模态数据集,规模达百亿级,旨在支持类似GPT-4级别的大型多模态模型训练。该数据集包含86亿张图像和1696亿个文本标记,远超现有数据集规模并保持高质量,具备广泛来源和灵活性,可轻松转换为纯文本或图像-文本对。经验证,该数据集质量优良,有望促进多模态模型研究,但同时也面临存储管理、数据偏见及隐私保护等挑战。
564 61
|
12月前
|
索引 搜索推荐 UED
基于elasticsearch + huggingface model 实现语义检索
项目地址:https://github.com/skyterra/elastic-embedding-searcher。本项目利用Hugging Face模型生成文本的嵌入向量,并将其同步至Elasticsearch创建索引,支持通过余弦相似度进行高效的向量搜索,实现精准的内容检索与推荐功能。该项目为开发智能搜索应用提供了强大的后端支持。 (该简介有239个字符,包括标点和空格)
375 8
|
11月前
|
存储 架构师 容灾
阿里云基础设施高可用最佳实践沙龙上海站圆满举办!
2025年1月9日,阿里云在上海虹桥绿地铂瑞酒店成功举办基础设施高可用最佳实践沙龙NO.1。活动吸引了华东地区多家企业的CTO、架构师和技术从业者参与。专家们分享了高可用的基础知识、分级标准及云端架构实战经验,涵盖计算、存储、网络和云原生等领域,重点讨论了企业如何在阿里云上构建高可用数据中心。现场互动热烈,参会者与专家深入交流,探讨技术应用与合作机会。
WK
|
数据可视化 开发者 容器
QWidget类
QWidget 是 Qt 框架中的基础类,用于创建用户界面的可视化组件。它是所有 UI 组件的基类,提供绘制、布局、事件处理、样式设置和部件通信等功能。常见子类包括 QMainWindow、QDialog、QPushButton 等,支持灵活的窗口管理和丰富的用户交互。
WK
269 3
|
监控 程序员 芯片
DOS操作系统的发展历程
【10月更文挑战第15天】DOS操作系统的发展历程
639 2