liunx学习篇-进程间通信方式-管道

✊✊✊🌈本文主要讲解进程间通信方式-管道的相关概念以及通信如何构建,并搭配上实例代码来更好理解进程通信-管道的构建过程。

✨liunx学习篇-进程间通信方式-管道✨

📚一.管道

管道使用起来很简单,主要有无名管道和命名管道两种 。

🌲(1)无名管道(pipe)

	int pipe(int pipefd[2]);//创建并打开管道
	参数:
		pipefd[0]:读端
		pipefd[1]:写端
	返回值:
		成功:0
		失败:-1

🌷原理:内核借助了一个循环队列机制,使用内核缓冲区实现
🌷特点:

  1. 伪文件
  2. 管道中的数据只能一次读取
  3. 数据在管道中,只能单向流动(单向半双工)

🌷局限性:

  1. 自己写,但是不能自己读
  2. 数据不可以反复读取
  3. 单向半双工通信
  4. 血缘关系进程间使用

🌷管道的读写行为:

读管道:

  1. 管道有数据,read返回实际读到的字节数
  2. 管道无数据:
    (1)无写端,read返回0;
    (2)有写端,read阻塞等待;

写管道:

  1. 无写端,异常终止(SIGPIPE)
  2. 有读端,
    (1)管道已满,阻塞等待;
    (2)管道未满,返回写入字节数;
    (2)命名管道

🌲(2)命名管道(fifo)

fifo被称为命名管道,pipe用于有血缘关系的进程间通信,fifo,无血缘关系的进程也可以通信。
创建方式有两种:
1.直接通过指令创建mkfifo myfifo
2.通过库函数实现int mkfifo(const char*pathname,mode_t mode);
使用时需要使用open先打开,针对其使用文件IO相关操作

🔑二.实现

🍉1、无名管道(pipe)-父子进程间通讯

子进程负责写入,父进程负责读出。
1.子进程写入时,首先关闭读端pipefd[0],写入字符串str,写完之后关闭写端pipefd[1]。
2.父进程读出时,首先关闭写端pipefd[1],先将数据读入到缓冲区buf中,然后打印,之后关闭写端pipefd[0]。
💻 代码mypipo.c

	#include<unistd.h>
	#include<stdio.h>
	#include<stdlib.h>
	#include<string.h>
	int main(){
	        int ret;
	        int pipefd[2];
	        ret=pipe(pipefd);//创建并打开管道
	        char buf[1024];//缓冲区
	        char*str="hello! i am parent!\n";
	        if(ret==-1){
	            perror("pipe error!\n");
	            exit(1);
	        }
	        int pid=fork();//创建子进程
	        if(pid>1){//子进程
	            close(pipefd[0]);//close read
	            write(pipefd[1],str,strlen(str));
	            close(pipefd[1]);
	        }else if(pid==0){//父进程
	            close(pipefd[1]);//close write
	            ret=read(pipefd[0],buf,sizeof(buf));
	            write(STDOUT_FILENO,buf,ret);//
	            close(pipefd[0]);
	        }
	        return 0;
	}

🌻结果展示:
请添加图片描述

🍉 2、无名管道(pipe)-兄弟进程间通讯

进程间通讯不仅能传输数据,还能传输指令。
指令: ls wc -l 查看当前目录有多少子文件

💻 bropipe.c

	#include<stdlib.h>
	#include<stdio.h>
	#include<unistd.h>
	#include<string.h>
	#include<sys/wait.h>
	int main(){
	        int ret;
	        int fd[2];
	        ret=pipe(fd);  
	        if(ret==-1){
	            perror("pipe error!\n");
	            exit(1);
	        }
	        int i=0;
	        pid_t pid;
	      
			for(;i<2;i++){
	          pid =fork();
	          if(pid==-1){
	              perror("fork error!\n");
	              exit(1);
	          }
	          if(pid==0) break;
	        }
	
	        if(i==2){// parent 
	            close(fd[0]);
	            close(fd[1]);
	            wait(NULL);
	            wait(NULL);
	        }else if(i==0){//first child
	            close(fd[0]);//关闭读端
	            dup2(fd[1],STDOUT_FILENO);//通过文件重定向,将写端重定向到STDOUT_FILENO
	            execlp("ls","ls",NULL);//
	            perror("error!\n");//捕获异常
	        }else if(i==1){//second child
	            close(fd[1]);
	            dup2(fd[0],STDIN_FILENO);
	            execlp("ls","wc","-l",NULL);
	            perror("error!\n");
	        }
	}

🍉3、命名管道(fifo)-创建

💻 创建方式有两种:
1.直接通过指令创建

	mkfifo myfifo

2.通过库函数实现int mkfifo(const char*pathname,mode_t mode);

	#include<stdio.h>
	#include<sys/stat.h>
	#include<stdlib.h>
	int main(){
	        int ret=mkfifo("myfifo_1",0644);
	        if(ret==-1){
	                perror("mkfifo error!");
	                exit(1);
	        }
	        return 0;
	}

🌻结果展示:
请添加图片描述

🍉4、命名管道(fifo)-无血缘关系间通信

利用前面创建的命名管道myfifo和myfifo_1进行通信,fifo_w创建进程进行写,fifo_r创建进程进行读。
传输数据格式:

 hello 1
 hello 2
 hello 3
 ...

💻 fifo_w.c文件

	#include<stdio.h>
	#include<stdlib.h>
	#include<unistd.h>
	#include<string.h>
	#include <fcntl.h>
	int main(int argc,char* argv[]){
	        char buf[1024];
	        int fd=open(argv[1],O_WRONLY);
	        if(fd<0){
	            perror("open error!\n");
	            exit(1);
	        }
	        int i=1;
	        while(i){
	            sprintf(buf,"hello %d\n",i++);
	            write(fd,buf,strlen(buf));
	            sleep(1);
	        }
	        close(fd);
	        return 0;
	}

💻 fifo_r.c文件

	#include<stdio.h>
	#include<stdlib.h>
	#include<unistd.h>
	#include<string.h>
	#include <sys/types.h>
	#include <sys/stat.h>
	#include <fcntl.h>
	int main(int argc,char* argv[]){
	        char buf[1024];
	        int fd=open(argv[1],O_RDONLY);
	        if(fd<0){
	            perror("open error!\n");
	            exit(1);
	        }
	        int ret;
	        while(1){
	            ret=read(fd,buf,strlen(buf));
	            write(STDOUT_FILENO,buf,ret);
	           sleep(1);
	        }
	        close(fd);
	        return 0;
	}

🌻结果展示:
请添加图片描述
请添加图片描述
OK,以上就是本期“linux学习篇-进程间通信方式-管道”的内容啦~~ ,感谢友友们的阅读。后续还会继续更新,欢迎持续关注哟📌~
💫如果有错误❌,欢迎批评指正呀👀~让我们一起相互进步🚀
🎉更新不易,觉得文章写得不错的小伙伴们,点赞评论关注走一波💕💕~~~谢谢啦🙏 🙏🙌

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

君莫笑lucky

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值