Linux进程通信之管道(FIFO)

1. 何为管道

我的理解就是管道是一个类似于队列的缓冲区,数据先进先出。一个进程发送数据,一个进程接受数据

2. 管道分类

2.1 无名管道

无名管道适用于有亲缘关系的进程,如父子进程。因为子进程的内存空间是直接拷贝的父进程的内存空间,所以父进程创建管道后得到的文件描述符也被拷贝了一份,而其他没有亲缘关系的进程则无法的到该文件描述符(没有文件名与之对应)。

创建无名管道的接口:

 #include <unistd.h>
int pipe(int pipefd[2]);

例子:

#include<stdio.h>
#include<unistd.h>

/* 父进程生成数据, 子进程取出数据并打印 */
int main(void)
{
	int fd[2];
	int ret = 0;
	int data = 0;

	ret = pipe(fd);
	if (ret < 0) {
		perror("pipe error");
		return -1;
	}

	ret = fork();

	if (ret == 0) { // 子进程
		while(1) {
			ret = read(fd[0], &data, sizeof(data));
			if (ret < 0) {
				printf("read error");
				return -1;
			}
			printf("data: %d\n", data);
	
		}
	}
	else {		// 父进程
		while(1) {
			data += 1;
			write(fd[1], &data, sizeof(data));
			sleep(1);	// 一秒钟产生一个数据
		}
	}
	close(fd[0]);
	close(fd[1]);
	return 0;
}

2.2 有名管道

有名管道在没有亲缘关系的进程之间也能够使用,顾名思义,有名管道就是给管道命一个名字,也就是创建了一个文件,该文件称为管道文件。与普通文件不同的是,管道文件的数据是先进先出的,每个数据只能取一次,取了就没了,并且不能够使用lseek函数改变偏移量。

需要注意:

  • 管道建立好后,在打开管道文件的时候,管道的两端读写必须分别打开,有任何一方未打开,则在调用open的时候就阻塞。比如,一个进程以写的方式打开管道文件,但没有任何进程以读的方式打开,那么就会阻塞在open函数,直到某个进程取以读的方式打开管道文件
  • 管道大小是有最大值的,可以使用宏PIPE_BUF(limits.h)查看。
  • 管道默认是阻塞的,在没有数据可读的时候,读操作会阻塞。

例子:
read_pipe.c

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

#define FIFO_NAME	"./fifo_test"

/* 读取管道内的数据并打印, 每两秒读取一次 */
int main(void)
{
	int ret = 0;
	int fifo_fd;
	int data = 0;

	// 打开管道
	fifo_fd = open(FIFO_NAME, O_RDONLY);
	if (fifo_fd < 0) {
		perror("open fifo error");
		return -1;
	}
	printf("[read] open ok\n");
	while(1) {
		// 读取数据
		ret = read(fifo_fd, &data, sizeof(data));
		if (ret < 0) {
			perror("read error");
			return -1;
		}
		printf("data: %d\n", data);
		sleep(2);
	}
	close(fifo_fd);
	return 0;
}

write_pipe.c

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

#define FIFO_NAME	"./fifo_test"

/* 创建管道, 向管道内写入数据,每一秒写入一次 */
int main(void)
{
	int ret = 0;
	int fifo_fd;
	//char *data = "hello World";
	int data = 0;


	// 没有就创建
	if (access(FIFO_NAME, F_OK) == -1) {
		ret = mkfifo(FIFO_NAME, 0777);
		if (ret < 0) {
			perror("mkfifo error\n");
			return -1;
		}
	}
	// 打开管道
	fifo_fd = open(FIFO_NAME, O_WRONLY);
	if (fifo_fd < 0) {
		perror("open fifo error");
		return -1;
	}
	printf("[write] open ok\n");
	while(1) {
		// 写入数据
		data += 1;
		write(fifo_fd, &data, sizeof(data));
		sleep(1);
	}
	close(fifo_fd);
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值