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

团队提供丰富嵌入式项目学习,以及嵌入式方向毕业设计指导,欢迎咨询。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Linux管道是一种进程间通信方式,可以用于实现一个进程将数据传递给另一个进程。它是一种半双工的通信方式,即数据只能在一个方向上流动,而且只能在建立了父子进程关系的进程之间使用。 下面是使用管道实现进程间通信的基本步骤: 1. 创建管道 首先需要使用系统调用pipe()创建一个管道。这个函数会返回两个文件描述符,一个用于读取管道数据,一个用于写入管道数据。 2. 创建子进程 接下来需要使用系统调用fork()创建一个子进程。这个函数会返回两次,一次在父进程中返回子进程的PID,另一次在子进程中返回0。 3. 父进程写入数据 在父进程中,可以通过写入管道文件描述符来将数据传递给子进程。可以使用系统调用write()将数据写入管道。 4. 子进程读取数据 在子进程中,可以通过读取管道文件描述符来获取父进程传递的数据。可以使用系统调用read()从管道中读取数据。 5. 关闭管道 当通信结束后,需要关闭管道。可以使用系统调用close()关闭管道的读取和写入端。 下面是一个简单的代码示例,演示了如何使用管道实现进程间通信: ``` #include <stdio.h> #include <unistd.h> int main() { int fd[2]; pid_t pid; char buf[256]; // 创建管道 if (pipe(fd) < 0) { fprintf(stderr, "pipe error\n"); return -1; } // 创建子进程 if ((pid = fork()) < 0) { fprintf(stderr, "fork error\n"); return -1; } else if (pid > 0) { // 父进程写入数据 close(fd[0]); // 关闭读取端 write(fd[1], "hello world\n", 12); close(fd[1]); // 关闭写入端 } else { // 子进程读取数据 close(fd[1]); // 关闭写入端 read(fd[0], buf, sizeof(buf)); printf("received data from parent: %s", buf); close(fd[0]); // 关闭读取端 } return 0; } ``` 在这个示例中,我们首先创建了一个管道,然后使用fork()创建了一个子进程。在父进程中,我们通过write()将数据写入管道中;在子进程中,我们通过read()从管道中读取数据。最后,我们分别关闭了管道的读取和写入端。 注意,管道的缓冲区大小是有限的,如果写入的数据超过了缓冲区的大小,写入操作会被阻塞,直到有足够的空间。同样地,如果读取的数据为空,读取操作也会被阻塞,直到有数据可读取。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

河边小乌龟爬

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

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

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

打赏作者

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

抵扣说明:

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

余额充值