linux下进程通信(无名管道和有名管道FIFO)

一、什么是管道

管道是从unux继承过来的最早的IPC通讯方式之一,它有如下特点:

  • 管道数据的读写是半双工的,即只能从写端写入,从读端读出;
  • 管道数据不能重复读取,一旦调用read读取写入管道的数据,这段数据将永久从管道中移除,不能被其它进程获取;
  • 管道有点类似于队列,允许用户向其中连续放入多条内容,然后可以逐条取出;

二、有名管道和无名管道

2.1、无名管道

  • 无名管道的存在依赖于创建它的进程,当进程退出后,无名管道的资源也会自动释放;
  • 无名管道通信只能用于具有亲缘关系的进程之间的通讯(有名管道没有这个限制);

2.2、有名管道

  • 有名管道也叫FIFO,它在linux系统中作为一种特殊的文件而存在,并具有文件系统中的inode信息。
  • 有名管道(FIFO)创建之后是独立存在的,它不依赖于创建它的进程,因此任何进程可以根据FIFO的名称来打开并进行读写操作;
  • 读写FIFO的两个进程调用open打开同一个FIFO文件是会得到相同的文件描述符;
  • 有名管道(FIFO)在创建之后如果不再使用,需要主动删除,否则它会一直存在于系统之中;
  • 我们可以把FIFO简单理解成一个文件,只是FIFO不能用open或者create等普通文件的创建方式来创建,而需要用mkfifo函数来创建。使用mkfifo创建一个FIFO之后,我们就可以把FIFO当成普通文件来使用open打开,使用read和write进行读写。

四、管道相关函数

4.1、pipe函数

int pipe(int pipefd[2]);
  • pipe创建一个无名管道,pipfd用于指向管道两端的描述符。fppfd[0]指向读端,pipfd[1]指向管道的写端;
  • 数据从管道写段写入,从管道读端读出,使用pipe创建得到的pipefd指向的是内存中的某一块内存,这块内存由系统分配,之后可以调用read和write对pipefd进行读写操作。

4.2、mkfifo函数

#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
  • mkfifo用来创建一个有名管道(FIFO),它的第一个参数指定一个路径名,mode指定FIFO的权限,如0666表示具有可读和可写权限。
  • mkfifo调用成功返回0,失败返回-1。

示例:

fifo_read.c

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

int main()
{
	int ret = -1;
	char *path = "/myfifo";
	char buffer[1024];
	int fd = -1;
	
	if(0 != access(path,F_OK))//如果文件不存在,创建FIFO文件
	{
		ret = mkfifo(path,0666);
		if(0 != ret)
		{
			perror("mkfifo error\r\n");
			return -1;
		}
	}
	
	fd = open(path,O_RDONLY);
	if(0 > fd)
	{
		perror("open fifo error\r\n");
		return -1;
	}
	printf("read fifo fd:%d\r\n",fd);
	while(1)
	{
		memset(buffer,0,sizeof(buffer));
		if(read(fd,buffer,sizeof(buffer))<=0)
		{
			perror("read error");
			break;
		}
		printf("read fifo:%s",buffer);
		if(0 == strncmp(buffer,"exit",4))
		{
			break;
		}
	}
	printf("read process exit\r\n");
	close(fd);
}

fifo_write.c

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

int main()
{
	int ret = -1;
	char *path = "/myfifo";
	char buffer[1024];
	int fd = -1;
	
	if(0 != access(path,F_OK))//如果文件不存在,创建FIFO文件
	{
		ret = mkfifo(path,0666);
		if(0 != ret)
		{
			perror("mkfifo error\r\n");
			return -1;
		}
	}
	
	fd = open(path,O_WRONLY);
	if(0 > fd)
	{
		perror("open fifo error\r\n");
		return -1;
	}
	printf("write fifo fd:%d\r\n",fd);
	while(1)
	{
		printf("write some data:");
		ret = fgets(buffer,1024,stdin);
		if(write(fd,buffer,sizeof(buffer))<0)
		{
			perror("write error");
			break;
		}
		if(0 == strncmp(buffer,"exit",4))
		{
			break;
		}
	}
	printf("write process close fd\r\n");
	close(fd);
}
gcc fifo_write.c -o write
gcc fifo_read.c -o read

分别在两个shell中运行read和write,运行结果如下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ly5jmaa9-1598971618139)(9C90312453454330B9566D456F589A14)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值