【Linux】匿名管道pipe和有名管道fifo详解

创作不易,本篇文章如果帮助到了你,还请点赞 关注支持一下♡>𖥦<)!!

主页专栏有更多知识,如有疑问欢迎大家指正讨论,共同进步!

🔥Linux系列专栏:Linux基础 🔥

给大家跳段街舞感谢支持!ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ


目录

一、进程间通信IPC

进程间通信是操作系统提供的一种机制,用于多个进程之间进行数据通信,实现资源协调与共享。

IPC:Interprocess Communication 进程间通信

例如在单任务处理器中,多个进程之间就依靠着进程间通信 调度CPU,使得多个进程高效率并发执行

Linux中进程间通信的方式:

  • 管道:半双工通信方式,分为匿名管道(pipe)和有名管道(fifo),用于具有亲缘关系之间的进程通信
  • 消息队列:进程利用消息队列通过发送和接收消息进行通信
  • 信号:主要用于消息的通知和进程控制,不能传输大量数据,仅作为一种简单的通信方式
  • 内存共享映射:多个进程可以共享同一块内存,可以实现数据共享,需要同步互斥机制
  • Socket套接字:支持全双工通信,数据可以在任意时刻发送和接收,常用于网络通信

二、匿名管道pipe

匿名管道用于具有亲缘关系 的进程之间的通信,无法与其他进程进行通信。

使用方法

在管道使用前需要先确定数据传输的方向,只能用于单向通信,即数据只能从一端写入,从另一端读取。

调用pipe(int fd[2])函数后,进程将会在内核层创建一个管道缓冲区 (环形队列),当管道被创建成功后,将会传出两个文件描述符:fd[0]为读取 ,fd[1]为写入文件描述符。

由于子进程会继承父进程的文件描述符表,父进程和子进程可以分别获得一个文件描述符,父子进程间传输数据就依靠这两个文件描述符。

使用举例:

cpp 复制代码
#include <fcntl.h>
#include <sys/wait.h>
#include <string.h>
#include <stdio.h>
int main()
{
	pid_t pid;
	int fd[2]; //读取和写入文件描述符号
	pipe(fd);  

	pid = fork();
	if(pid > 0) //父进程
	{
		close(fd[0]);  //确定通信方向:关闭读端
		char* str = "TianXiStudio";
		write(fd[1],str,strlen(str));
		close(fd[1]);  //写入完成,关闭写入文件描述符
		wait(NULL);     //回收僵尸进程
		exit(0);
	}
	else if(pid == 0)  //子进程
	{
		close(fd[1]);  //确定通信方向:关闭写端

		char buf[1024];
		bzero(buf,sizeof(buf));

		read(fd[0],buf,sizeof(buf));  //从管道中读取数据
		printf("read:%s\n",buf);

		close(fd[0]);  //读取完成,关闭读取文件描述符
		exit(0);
	}
	else
	{
		perror("fork failed");
		exit(0);
	}
	return 0;
}

子进程从管道中读取数据:

匿名管道的特点

  • 匿名管道被亲缘关系所限制,无法与其他进程进行通信
  • 只能用于单向通信,数据只能从一个方向流动
  • 基于字节流进行通信,数据按照顺序写入和读取
  • 有名管道可以作为临时存储介质,例如:ubuntu16.04中管道缓冲区为4K大小
  • 管道的生命周期随着进程的结束而结束,管道的回收使用管道引用计数
  • 由于管道是半双工通信方式,支持异步通信,自带同步互斥
  • 当管道缓冲区为空或已满时,将会造成读取或写入阻塞
  • 使用管道通信时,需要确保及时关闭管道。读取端关闭时,写入端仍写入数据时,写入端进程将会被SIGPIPE杀死。写入端关闭时,读取端读取管道数据后返回0。

三、有名管道fifo

有名管道是一种特殊的文件类型,存在于文件系统中,但并不是用于存储数据的,而是用于进程间通信。

相比于匿名管道的亲缘间通信,有名管道可以支持非亲缘关系之间的通信

使用方法

使用命令mkfifo或函数mkfifo()来创建管道文件,两个进程间通过打开管道文件后使用read()函数读取或write()写入,进行通信。

管道文件本身不能存储,通过重定向到管道缓冲区中,对管道文件读写就会对管道缓冲区进行读写当进程不再需要使用管道时,应关闭管道文件描述符。

写入进程:

cpp 复制代码
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main()
{
	int fd = open("fifo",O_WRONLY);
	char* str = "TianXiStudio";
	write(fd,str,strlen(str));
	close(fd);
	return 0;
}

读取进程:

cpp 复制代码
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>

int main()
{
	int fd = open("fifo",O_RDONLY);
	char buffer[1024*4];
	read(fd,buffer,sizeof(buffer));
	printf("read :%s\n",buffer);
	close(fd);
	return 0;
}

有名管道的特点

  • 数据在内存中进行传输,避免了不必要的磁盘I/O操作
  • 有名管道的文件存在不会随着进程的结束而消失
  • 只有读写两个进程都进行,有名管道才能打开使用,否则会阻塞等待

|--------------------------------------|
| 大家的点赞、收藏、关注将是我更新的最大动力! 欢迎留言或私信建议或问题。 |

|---------------------------------------------------------------|
| 大家的支持和反馈对我来说意义重大,我会继续不断努力提供有价值的内容!如果本文哪里有错误的地方还请大家多多指出(●'◡'●) |

相关推荐
dr李四维1 分钟前
iOS构建版本以及Hbuilder打iOS的ipa包全流程
前端·笔记·ios·产品运营·产品经理·xcode
cherub.3 分钟前
深入解析信号量:定义与环形队列生产消费模型剖析
linux·c++
暮色_年华17 分钟前
Modern Effective C++item 9:优先考虑别名声明而非typedef
c++
重生之我是数学王子25 分钟前
QT基础 编码问题 定时器 事件 绘图事件 keyPressEvent QT5.12.3环境 C++实现
开发语言·c++·qt
梅见十柒26 分钟前
wsl2中kali linux下的docker使用教程(教程总结)
linux·经验分享·docker·云原生
Koi慢热29 分钟前
路由基础(全)
linux·网络·网络协议·安全
CV学术叫叫兽38 分钟前
一站式学习:害虫识别与分类图像分割
学习·分类·数据挖掘
传而习乎40 分钟前
Linux:CentOS 7 解压 7zip 压缩的文件
linux·运维·centos
入 梦皆星河42 分钟前
在 Ubuntu/Debian 上安装 Go
ubuntu·golang·debian
我们的五年1 小时前
【Linux课程学习】:进程程序替换,execl,execv,execlp,execvp,execve,execle,execvpe函数
linux·c++·学习