进程的管道通信_进程 管道

进程的管道通信_进程 管道管道最大64K,由环形队列组成。需要占用两个文件描述符,分别作为管道读端、写端。管道是半双工的,需要确定通信方向。

管道

  • 什么是管道?
    一个进程连接到另一个进程的一个数据流称为一个“管道”。

匿名管道pipe

  • 用于父子间的通信
  • 管道最大64K,由环形队列组成
  • 需要占用两个文件描述符,分别作为管道读端、写端
  • 管道是半双工的,需要确定通信方向
    父写子读,关闭父读、子写
    子写父读,关闭子读、父写
  • 优点:稳定、经典

pipe函数原型

头文件:<unistd.h>

int pipe(int file_descriptor[2]);

功 能:创建一无名管道
参 数:file_descriptor:文件描述符数组,其中file_descriptor[0]表示读端,file_descriptor[1]表示写端
返回值:成功返回0,失败返回-1

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

进程的管道通信_进程 管道


1、父进程调用pipe开辟管道,得到两个文件描述符指向管道的两端。
2、父进程调用fork创建子进程,那么子进程也有两个文件描述符指向同一管道。
3、父进程关闭管道读端,子进程关闭管道写端。父进程可以往管道里写,子进程可以从
4、管道里读,管道是用环形队列实现的,数据从写端流入从读端流出,这样就实现了进程间通信。

#include <stdlib.h>
#include <unistd.h>

#define MAXLINE 80

int main(void)
{
	int n;
	int fd[2];
	pid_t pid;
	char line[MAXLINE];

	if (pipe(fd) < 0) 
	{
		perror("pipe");
		exit(1);
	}
	if ((pid = fork()) < 0) 
	{
		perror("fork");
		exit(1);
	}
	if (pid > 0) // 父进程 
	{ 
		close(fd[0]);//关闭读端
		write(fd[1], "hello world\n", 12);
		wait(NULL);
	}
	else  //子进程
	{
		close(fd[1]);//关闭写端
		n = read(fd[0], line, MAXLINE);
		write(STDOUT_FILENO, line, n);
	}
	return 0;
}

运行结果

进程的管道通信_进程 管道

注意事项

  • 如果试图从管道写端读取数据,或者向管道读端写入数据都将导致错误发生
  • 写端未写完,写端暂时无数据,读端再次去读,read发生阻塞(读太快)
  • 读端未读完,写端满了,写端再次写,write发生阻塞(写太快)
  • 读端关闭,写端写数据,产生SIGPIPE信号,默认会终止进程
  • 写端关闭,当数据读完,再次读返回0

Linuxc/c++服务器开发高阶视频,电子书学习资料后台私信【架构】获取

进程的管道通信_进程 管道

进程的管道通信_进程 管道

有名管道fifo

pipe是有血缘关系进程之间的通信,那么当没有血缘关系的进程想要通信怎么办?

  • 创建一个有名管道fifo(也叫做named pipe),解决无血缘关系的进程通信
  • fifo是一个设备文件,本身无大小,在文件系统中以文件名的形式存在,因此即使进程与创建fifo的进程不存在血缘关系也依然可以通信,前提是可以访问该路径。
  • fifo总是遵循先进先出的原则,即第一个进来的数据会第一个被读走
进程的管道通信_进程 管道

与匿名管道pipe的区别

  • 提供了一个路径名与之关联,以fifo文件的形式存储于文件系统中,能够实现任何两个进程之间通信。而匿名管道对于文件系统是不可见的,它仅限于在父子进程之间的通信。 但是fifo底层是由pipe实现的。

如何创建fifo?

  • 命令行上创建
  • 程序内创建
    头文件:
    #include <sys/types.h>
    #include <sys/stat.h>
    函数原型:
    int mkfifo(const char *pathname, mode_t mode);

做个测试,分别写两个程序,一个写,一个读
写进程

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

int main(int argc, char* argv[])
{
	int fd;
	char buff[1024] = "hello world\n";

	if (argc < 2)
	{
		printf("enter you fifoname\n");
		exit(1);
	}
	fd = open(argv[1], O_WRONLY);//只写方式打开

	if (fd < 0)
	{
		perror("open\n");
	}

	write(fd, buff, strlen(buff));//写入hello world
	close(fd);

	return 0;
}

读进程

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

int main(int argc, char* argv[])
{
	int fd;
	int len;
	char buff[1024] = "hello world\n";

	if (argc < 2)
	{
		printf("enter you fifoname\n");
		exit(1);
	}
	fd = open(argv[1], O_RDONLY);//只写方式打开

	if (fd < 0)
	{
		perror("open\n");
	}

	len = read(fd, buff, sizeof(buff));
	write(STDOUT_FILENO, buff, len);
	close(fd);

	return 0;
}

测试结果如下

进程的管道通信_进程 管道


首先myfifo是我们提前创建好的fifo管道文件,然后执行写进程,再执行读进程。读到了hello world,执行前后myfifo文件大小都为0

注意事项

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/11690.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注