进程通信之有名管道

无名管道只能用于有亲缘进程之间的通信,有名管道可以实现无亲缘关系的通信。
有名管道 fifo 给文件系统提供一个路径,这个路径和管道关联,只要知道这个管道路径,
就可以进行文件访问,fifo 是指先进先出,也就是先写入的数据,先读出来。

特点:

a、有名字,储存于普通文件系统中
b、任何具有相应权限的进程都可以使用open()来获取FIFO的文件描述符
c、跟普通文件一样,用read()和writ()来读和写
d、不能用lseek来定位
e、支持多写入者同时进行写操作而数据不会相互践踏

mkfifo 的用法

int mkfifo(const char *pathname, mode_t mode);
参数*pathname:路径名,管道名称。
参数 mode:管道的权限。
返回值:成功返回 0,错误返回-1。

无名管道例程:

1、create.c(创建无名管道,创建源文档)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void filecopy(FILE *ifp,char *buff);

int main(void)
{
	char buff[]="Everything that kills me makes me feel alive!\n";
	long int times = 100000;
	char *file1 = "/home/test/fifotest/date.txt";
	FILE *fp1;
	
	if((fp1 = fopen(file1,"a+")) == NULL)
	{
		printf("can't open the file %s\n",file1);
		exit(1);
	}
	
	printf("Wrinting is begin\n");
	
	while(times--)
		filecopy(fp1,buff);
	
	fclose(fp1);
	
	printf("Wrinting is over\n");
	
	return 0;
}

void filecopy(FILE *ifp,char *buff)
{
	int i,j;
	j = 0;
	i = strlen(buff)-1;
	while(i--)
	{
		putc(buff[j],ifp);
		j++;
	}
	putc('\n',ifp);
}

2、writefifo.c(写入有名管道)

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

void main()
{
	const char* fifo_name = "/home/topeet/test/fifotest/fifo_exchange";
	char *file1 = "/home/topeet/test/fifotest/data.txt";
	int pipe_fd = -1;
	int data_fd = -1;
	int bytes_read = 0;
	int bytes_sent = 0;
	int res_read = -1;
	int res_sent = -1;
	int res = -1;
	char buffer[PIPE_BUF+1];
	
	if(access(fifo_name,F_OK) == -1)
	{
		res = mkfifo(fifo_name,0777);
		if(res != 0)
		{
			fprintf(stderr,"Could not create fifo %s\n",fifo_name);
			exit(EXIT_FAILURE);
		}
	}
	
	printf("Process %d opening FIFO O_WRONLY\n",getpid());
	
	pipe_fd = open(fifo_name,O_WRONLY);
	data_fd = open(file1,O_RDONLY);
	
	printf("Process %d result %d,data_fd of file is %d\n", getpid(), pipe_fd,data_fd);
	
	//从数据文件读取数据
	if(pipe_fd != -1)
	{
		res_read = 0;
		res_read = read(data_fd,buffer,PIPE_BUF);
		buffer[res_read] = '\0';
		bytes_read += res_read;
			
	//第一次读取成功,写入FIFO文件
		
		while(res_read>0)
		{
			res_sent = write(pipe_fd,buffer,res_read);
			if(res_sent == -1)
			{
				fprintf(stderr, "Write error on pipe\n"); 
				exit(EXIT_FAILURE);
			}
			bytes_sent += res_sent;
			res_read = read(data_fd,buffer,PIPE_BUF);
			buffer[res_read] = '\0';
			bytes_read += res_read;
		}
		fprintf(stderr, "%d bytes of data were read in all,%d bytes of data were write in all\n",bytes_read,bytes_sent);

		close(pipe_fd);
		close(data_fd);
		//关闭文件
	}
	else
		exit(EXIT_FAILURE);

	printf("Process %d finished\n", getpid());
	exit(EXIT_SUCCESS);
	//退出程序
}

3、readfifo.c(从有名管道读出)

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

int main()
{
	const char *fifo_name = "/home/test/fifotest/fifo_exchange";
	char *write_file = "/home/test/fifotest/write.txt";
	int pipe_fd = -1;
	int write_fd = -1;
	int bytes_read = 0;
	int bytes_write = 0;
	int res_read = 0;
	int res_write = 0;
	char buffer[PIPE_BUF+1];
	//清空缓冲数组  
    memset(buffer, '\0', sizeof(buffer));
	
	printf("Process %d opening FIFO O_RDONLY\n", getpid());
	//以只读方式打开FIFO文件
	pipe_fd = open(fifo_name,O_RDONLY);
	//以只写方式创建保存数据的文件
	write_fd = open(write_file,O_WRONLY|O_CREAT, 0644);
	
	if(pipe_fd == -1)
	{
		printf("Opened the fifo file failure!\n");
		exit(1);
	}
	
	if(write_fd == -1)
	{
		printf("Created the write file failure!\n");
		exit(1);
	}
	
	printf("Process %d result %d,write_fd of file is %d\n", getpid(), pipe_fd,write_fd);
	
	//读取FIFO文件中数据,并保存至Dateformfifo文件中
	do
	{
		res_read = read(pipe_fd,buffer,PIPE_BUF);
		res_write = write(write_fd,buffer,res_read);
			if(res_write == -1)
			{
				printf("Read file failed\n");
				exit(1);
			}
		bytes_read += res_read;
		bytes_write += res_write;
		
	}
	while(res_read>0);
	
	printf("Process %d finished\n", getpid());
		
	close(pipe_fd);
	close(write_fd);
	
		printf("%d bytes of data were read in all,%d bytes of data were write in all\n",bytes_read,bytes_write);

	exit(0);
}

编译运行测试

使用gcc命令对create.c、writefifo.c、readfifo.c文件进行编译,ls查看。
在这里插入图片描述

使用 ./create命令,创建文本文件。如图,多了data.txt文件。
在这里插入图片描述

vim data.txt查看文本文件内容。

在这里插入图片描述

使用**./writefifo &**命令,生成有名管道。ls查看如图。
在这里插入图片描述

使用**./readfifo命令从管道内读取数据转存。使用ls**查看。

在这里插入图片描述

查看write.txt文件内容。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值