Linux基础——管道

管道创建主要是两种:无名管道和有名管道(命名管道)

无名管道(pipe函数)

  • 需要的头文件:#include <unistd.h>

  • 函数: int pipe(int pipefd[2]);

  • 主要创建无名管道的方式:

int pipefd[2];	//名字随意
if(pide(pipefd)<0)
{
	//创建失败就报错
	perror("pipe");
	exit(1);
}
  • 返回值:成功为0,失败为-1
  • 无名管道的受限范围:无名管道是用于血缘进程(父子进程)之间的通信,如果两个进程不是血缘进程,那么无法进行通信
  • 无名管道原理:这种管道建立之后,他们会在进程中占用两个文件符的位置,一个专门来读,一个专门来写,如下的左图。具有方向性要么是父写子读,关闭父读子写,要么就是子写父读,关闭父写子读,他们之间是通过计算机的内核来实现的。看下图中,红黑箭头只能存在一种(箭头方向代表信息传递方向)。

无名管demo:

#include<sys/types.h>
#include<sys/stat.h> 
#include<unistd.h>
#include<fcntl.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
	int fd[2];
	pid_t pid;
	//创建管道
	if(pipe(fd) < 0)
	{
		//如果返回的是-1就代表创建失败,0代表成功
		perror("pipe");
		exit(1);
	}
	
	//创建父子进程
	pid = fork();
	char str[1024] = "hello linux\n";
	char buf[1024];
	//父进程
	if(pid > 0)
	{
		close(fd[0]);	//父进程关闭读
		write(fd[1],str,strlen(str));
	}
	else if(pid == 0)	//子进程
	{
		int len;
		close(fd[1]);	//子进程关闭写
		len = read(fd[0],buf,sizeof(buf));	
		write(STDOUT_FILENO,buf,len);		//以标准形式输出
	}
	else
	{
		perror("fork");	//进程异常处理
		exit(1);
	}
	while(1);
	return 0;
}

有名管道

有名管道用的是mkfifo,这个mkfifo有指令,也有函数。有名管道的原理和无名管道类似,都是通过一个中转的地方来通信,但是有名管道不是通过内核,而是通过磁盘创建一个节点来进行信号的中转,该节点不占空间。

有名管道特性

  • 当只写打开FIFO管道时,如果没有FIFO没有读端打开,则open写打开会阻塞。
  • FIFO内核实现时可以支持双向通信。(pipe单向通信,因为父子进程共享同一个file 结构体)
  • FIFO可以一个读端,多个写端;也可以一个写端,多个读端

方法一:使用mkfifo函数

  • 需要的头文件:#include <sys/types.h> 和 #include <sys/stat.h>
  • 函数:int mkfifo(const char *pathname, mode_t mode)
  • 参数解析:第一个参数为创建出来的的管道文件名称,第二个参数是该文件的权限
  • 返回值:-1失败,0为成功
  • 示例demo(这里我分三个文件来写)

创建有名管道的文件,该文件要先执行来创建一个管道

#include<sys/types.h>
#include<sys/stat.h> 
#include<unistd.h>
#include<fcntl.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	int ret;
	//先删除一下文件,防止重复创建
	unlink("FileTP");
	
	//创建命名管道,权限为 rwx rwx rwx的文件(0表示无特殊权限s)
	ret = mkfifo("FileTP",0777);
	if(ret==0)
	{
	 printf("创建命名管道成功\n");
	}
	else //返回值为-1
	{
	 printf("创建失败\n");
	}
	
	return 0;
}

读数据端的文件

#include<sys/types.h>
#include<sys/stat.h> 
#include<unistd.h>
#include<fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
	int fd,len;
	char buf[1024];
	
	//打开命名管道
	fd = open("FileTP",O_RDONLY);
	if(fd == -1)
	{
		//输出报错,关闭程序
		 perror("文件打开失败\n");
	 	exit(1);
	}
	
	len = read(fd,buf,sizeof(buf));
	
	//write(STDOUT_FILENO,buf,len);
	printf("%s\n",buf);
		
	close(fd);
	return 0;
	}

写数据端的文件

#include<sys/types.h>
#include<sys/stat.h> 
#include<unistd.h>
#include<fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
	int fd;
	char buf[] = "hello linux\n";
	
	printf("开始运行\n");
	fd = open("FileTP",O_WRONLY);
	if(fd == -1)
	{
		//输出报错,关闭程序
		perror("文件打开失败\n");
		exit(1);
 
	}
	else
	{
		printf("成功打开了文件\n");
	}

	//写文件
	write(fd,buf,sizeof(buf));
	printf("写完了\n");
	
	close(fd);	
	return 0;
}

注意:执行的时候,当只写打开FifeTP管道时,如果没有FifeTP没有读端打开,则open写打开会阻塞。即,你执行写文件的时候,程序是不走的,只有你打开另外一个终端执行读文件时,写文件的程序才会执行(用两个终端执行两个文件)

方法二:使用mkfifo指令

在终端输入mkfifo 管道名 来创建有名管道。方法和上面的一样,只是省去了创建管道文件那个操作。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值