Linux多进程间通信——管道通信实现

Linux多进程间通信——管道通信实现

之前分享了linux多进程间通信的两种方法,套接字和共享内存通信。今天来分享一下另外一种多进程通信方法——管道。

管道分为有名管道和无名管道。无名管道用于有亲缘关系之间的进程,即父子进程之间。有名管道允许没有亲属关系的进程间使用。管道是连接读写进程的一个共享文件,允许进程以先进先出的方式写入和读出数据,发送进程以字符流的形式吧大量数据写入管道尾部,接收进程从管道头部接收数据。管道应互斥使用,大小在定义时就固定下来了,之后不能改变。

无名管道:下面先介绍一下创建无名管道的API

int fds[2];//这里定义管道的文件描述符,其中一个用于读,一个用于写
pipe(fds);//无名管道的创建接口

创建成功之后,fds[0]就相当于管道头部,用于读,fds[1]相当于管道尾部,用于写进程写入数据。

有名管道:下面再介绍一下创建有名管道的API,有名管道的创建与共享内存、消息队列的创建过程都是差不多的,我们都要标记我们创建的I管道,依此来让两个进程能在内存中识别用于通信的管道是哪一个。

//写进程
define FIFO "myfifo"//这里的宏定义就是定义一个管道标识,表明我们创建的管道叫“myfifo”
mkfifo(FIFO, 0666);//mkfifo就是管道创建API,这里名字叫“myfifo”的FIFO管道就创建成功了
fd = open(FIFO, O_WRONLY);//以只写方式打开管道
write(fd, buf, sizeof(buf));
//读进程,前面都一样
define FIFO "myfifo"//这样两个进程就能识别了
mkfifo(FIFO, 0666);
fd = open(FIFO, O_RDONLY);
read(fd, buf, sizeof(buf));

下面我就给出使用有名管道实现的多进程通信的代码:

写进程:

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

#define FIFO "myfifo" //创建一个管道通信的键值
#define BUFFER_SIZE 1024

int main(int argc, char* argv[]){
	char buf[BUFFER_SIZE];
	int real_write;
	int fd;
	int rw = 1;
	//FIFO是否存在,不存在则创建
	if(access(FIFO, F_OK) == -1){
		if(mkfifo(FIFO, 0666) < 0 && errno != EEXIST){
			printf("falied");
			exit(1);
		}
	}
	
	if((fd = open(FIFO, O_WRONLY)) == -1){
		printf("open failed\n");
		exit(1);
	}
	
	do{
		printf("请输入要写入管道的内容:\n");
		fgets(buf, BUFFER_SIZE, stdin);
		if((real_write = write(fd, buf, BUFFER_SIZE)) > 0){
			printf("第%d次写入管道:%s\n",rw++, buf);
		}
	}
	while(strlen(buf) != 0);
	close(fd);
	exit(0);
}

读进程:

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

#define FIFO "myfifo" //创建一个管道通信的键值
#define BUFFER_SIZE 1024

int main(int argc, char* agrv[]){
	char buff[BUFFER_SIZE];
	int real_read;
	int fd;
	int rc = 1;
	
	//如果FIFO已经存在则直接往下执行,不存在则创建
	if(access(FIFO, F_OK) == -1){
		if(mkfifo(FIFO, 0666) < 0 && errno != EEXIST){//创建一个管道
			printf("mkfifo failed\n");
			exit(1);
		}
	}
	//打开管道
	if((fd = open(FIFO, O_RDONLY)) == -1){
		printf("open failed\n");
		exit(1);
	}
	
	while(1){
		memset(buff, 0, BUFFER_SIZE);
		if((real_read = read(fd, buff, BUFFER_SIZE)) > 0){
			printf("第%d次读取管道:%s\n", rc++, buff);
		}
	}
	close(fd);
	exit(0);
}

读进程和写进程基本上一样的,只是在读写的一点区别。

下面展示一下效果,我在Ubuntu中编译之后运行:

image-20220624165705447
我是河边小乌龟爬,学习嵌入式软件开发路上的一名小学生,欢迎大家相互交流哇。更多内容关注公众号:河边小乌龟爬。

猜你喜欢

转载自blog.csdn.net/zhm1949/article/details/125449666