用有名管道文件实现两个进程之间的通信

1. 进程

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体

2. 有名管道

  1. 匿名管道,由于没有名字,只能用于亲缘关系的进程间通信。为了克服这个缺点,提出了有名管道(FIFO),也叫命名管道、FIFO 文件。
  2. 有名管道(FIFO)不同于匿名管道之处在于它提供了一个路径名与之关联,以 FIFO 的文件形式存在于文件系统中,并且其打开方式与打开一个普通文件是一样的,这样即使与 FIFO 的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过 FIFO 相互通信,因此,通过 FIFO 不相关的进程也能交换数据。
  3. 一旦打开了 FIFO,就能在它上面使用与操作匿名管道和其他文件的系统调用一样的 I/O 系统调用了(如read()、write() 和 close())。与管道一样,FIFO 也有一个写入端和读取端,并且从管道中读取数据的顺序与写入的顺序是一样的。FIFO 的名称也由此而来:先入先出。
  4. 有名管道(FIFO) 和匿名管道(pipe)有一些特点是相同的,不一样的地方在于:
    • FIFO 在文件系统中作为一个特殊文件存在,但 FIFO 中的内容却存放在内存中。
    • 当使用 FIFO 的进程退出后,FIFO 文件将继续保存在文件系统中以便以后使用。
    • FIFO 有名字,不相关的进程可以通过打开有名管道进行通信。

3. 创建两个有名管道文件

首先创建两个文件作为两个进程,分别取名为mk_fifoa和mk_fifob(注意,进程名不可与管道名相同)。
两个有名管道文件在一个文件内创建完即可。

利用mkfifo函数创建两个有名管道文件

int mkfifo(const char *pathname, mode_t mode);
  • 作用:创建一个有名管道文件
  • *pathname:有名管道文件的名称
  • mode:文件权限
  • 返回值:0 成功 -1 失败
	//创建有名管道文件fifoa
	int ret = -1;
	ret = mkfifo("fifoa",0666);
	//创建文件失败并且该文件不存在,若文件存在则正常执行
	if(-1 == ret && errno != EEXIST)
	{
		perror("mkfifoa error\r\n");
		return -1;
	}
	printf("create fifoa OK!\r\n");
	//创建有名管道文件fifob
	ret = mkfifo("fifob",0666);
	if(-1 == ret && errno != EEXIST)
	{
		perror("mkfifob error\r\n");
		return -1;
	}
	printf("create fifob OK!\r\n");

4. 进程通信

4.1 进程mk_fifoa

4.1.1 打开两个有名管道文件并循环写入数据

利用IO所学的知识,使用文件IO打开
头文件:

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

有名管道通信
进程mk_fifoa先向管道文件fifoa内写入数据,然后由mk_fifob进程读出。完成进程mk_fifoa向进程mk_fifob通信

	//打开文件fifoa,先把数据写入到fifoa中
	int fdw = open("fifoa",O_WRONLY,0666);
	if(-1 == fdw)
	{
		perror("open errer\r\n");
		return -1;
	}
	printf("open fifoa OK!\r\n");
	//打开文件fifob,读取从进程mk_fifob中写入的数据
	int fdr = open("fifob",O_RDONLY,0666);
	if(-1 == fdr)
	{
		perror("open error\r\n");
		return -1;
	}
	printf("open fifob OK!\r\n");
	//定义一个数组存放数据
	char buf[BUF_SIZE] = {0};
	//循环通信
	while(1)
	{
		//先写入
		memset(buf,0,BUF_SIZE);
		fgets(buf,BUF_SIZE,stdin);
		write(fdw,buf,BUF_SIZE);

		//读出
		memset(buf,0,BUF_SIZE);
		read(fdr,buf,BUF_SIZE);
		printf("b -> a: %s",buf);
	}

	//关闭文件
	close(fdw);
	close(fdr);

4.2 进程mk_fifob

4.2.1 打开两个有名管道文件并循环写入数据

进程mk_fifob刚好与进程mk_fifoa相反先读出在写入
进程mk_fifob再向管道文件fifob内写入数据,然后由mk_fifoa进程读出。完成进程mk_fifob向进程mk_fifoa通信。

	//打开文件fifoa
	int fdr = open("fifoa",O_RDONLY,0666);
	if(-1 == fdr)
	{
		perror("open error\r\n");
		return -1;
	}
	printf("open fifoa OK!\r\n");
	//打开文件fifob
	int fdw = open("fifob",O_WRONLY,0666);
	if(-1 == fdw)
	{
		perror("open error");
		return -1;
	}
	printf("open fifob OK!\r\n");

	char buf[BUF_SIZE] = {0};
	while(1)
	{
		//先读
		memset(buf,0,BUF_SIZE);
		read(fdr,buf,BUF_SIZE);
		printf("a -> b: %s",buf);

		//写
		memset(buf,0,BUF_SIZE);
		fgets(buf,BUF_SIZE,stdin);
		write(fdw,buf,BUF_SIZE);
	}

	close(fdr);
	close(fdw);

5. 运行结果

完成通信
在这里插入图片描述

6. 完整代码

6.1 进程mk_fifoa

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

#define BUF_SIZE 20

int main()
{
	//创建有名管道文件1
	int ret = -1;
	ret = mkfifo("fifoa",0666);
	if(-1 == ret && errno != EEXIST)
	{
		perror("mkfifoa error\r\n");
		return -1;
	}
	printf("create fifoa OK!\r\n");
	//创建有名管道文件2 
	ret = mkfifo("fifob",0666);
	if(-1 == ret && errno != EEXIST)
	{
		perror("mkfifob error\r\n");
		return -1;
	}
	printf("create fifob OK!\r\n");
	//打开文件fifoa
	int fdw = open("fifoa",O_WRONLY,0666);
	if(-1 == fdw)
	{
		perror("open errer\r\n");
		return -1;
	}
	printf("open fifoa OK!\r\n");
	//打开文件fifob
	int fdr = open("fifob",O_RDONLY,0666);
	if(-1 == fdr)
	{
		perror("open error\r\n");
		return -1;
	}
	printf("open fifob OK!\r\n");
	char buf[BUF_SIZE] = {0};
	while(1)
	{
		//先写入
		memset(buf,0,BUF_SIZE);
		fgets(buf,BUF_SIZE,stdin);
		write(fdw,buf,BUF_SIZE);

		//再读出
		memset(buf,0,BUF_SIZE);
		read(fdr,buf,BUF_SIZE);
		printf("b -> a: %s",buf);
	}

	//关闭文件
	close(fdw);
	close(fdr);
	return 0;
}

6.2 进程mk_fifob

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

#define BUF_SIZE 20

int main()
{
	//打开文件fifoa
	int fdr = open("fifoa",O_RDONLY,0666);
	if(-1 == fdr)
	{
		perror("open error\r\n");
		return -1;
	}
	printf("open fifoa OK!\r\n");
	//打开文件fifob
	int fdw = open("fifob",O_WRONLY,0666);
	if(-1 == fdw)
	{
		perror("open error");
		return -1;
	}
	printf("open fifob OK!\r\n");

	char buf[BUF_SIZE] = {0};
	while(1)
	{
		//先读
		memset(buf,0,BUF_SIZE);
		read(fdr,buf,BUF_SIZE);
		printf("a -> b: %s",buf);

		//写
		memset(buf,0,BUF_SIZE);
		fgets(buf,BUF_SIZE,stdin);
		write(fdw,buf,BUF_SIZE);
	}

	close(fdr);
	close(fdw);
}

本片文章就此结束了,目前进程学习还在进行中,只是把比较有意思的写出来分享一下,如有错误还请指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

居合啊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值