Linux 之管道通信

在这里插入图片描述

管道通信使用先入先出的原则进行读写,且不能是lseek函数定位读写位置。

(1)无名管道,无名管道是一种特殊类型的文件,完全由操作系统管理和维护,因为其存储位置只有亲缘关系的进程知道,所以只能用于亲缘关系的进程之间通信,而且,其内核资源会在两个通信进程退出后自动释放,无名管道创建函数为:

//from /usr/include/unistd.h
int pipe(int fd[2]);

函数pipe()返回两个文件描述符,其中fd[0]用来完成读操作,fd[1]完成写操作,默认阻塞方式。
以阻塞方式读管道时:
(1)有读进程,无写进程:

  1. 管道内无数据时,立即返回
  2. 管道内数据不足,读出所有数据
  3. 管道内数据充足,读出期望数据

(2)有读进程,有写进程:

  • 管道内无数据时,读进程阻塞
  • 管道内数据不足,读出所有数据
  • 管道内数据充足,读出期望数据

以阻塞方式写管道时:
(1)有写进程,无读进程:

  • 写进程将收到SIGPIPE信号,wirte函数返回-1

(2)有写进程,有读进程,且管道内有写空间:

  • 写入成功

另外可以使用fcntl()函数使用O_NDELAY或O_NONBLOCK属性,设置管道为非阻塞模式。

(2)有名管道
有名管道可以通过mknod 命令创建,也可以使用函数mkfifo()创建,可以使用在系统中任意两个进程之间进行通信,且创建的管道文件存储在硬盘上,不会随着进程结束而消失。mknod使用如下:

root@wangmumu-virtual-machine:/home/wangmumu/桌面/shares/FIFO# mknod fifo p
root@wangmumu-virtual-machine:/home/wangmumu/桌面/shares/FIFO# ls -l
总用量 24
prw-r--r-- 1 root   root       0  8月 26 00:30 fifo
-rwxr--r-- 1 nobody nogroup  872  8月 25 23:57 fifo_read.c
-rwxr--r-- 1 nobody nogroup  884  8月 25 23:52 fifo_write.c
-rwxr-xr-x 1 root   root    7613  8月 25 23:57 read
-rwxr-xr-x 1 root   root    7651  8月 25 23:52 write

可以看出已经创建了管道文件fifo。

函数声明如下:

// from /usr/include/sys/stat.h
int mkfifo(char* path,mode_t mode);

函数的第一个参数为有名管道文件,函数调用时,必须不存在,执行成功返回0,失败返回-1。
(1)当进程以写或读的方式打开管道文件,必须有另一个进程以相对应的读或写方式也打开该文件,否则该进程将阻塞在open()位置。
(2)若两个进程都已打开,但中途某进程退出,则:

  1. 读进程退出,返回SIGPIPE信号
  2. 写进程退出,读进程将不再阻塞,直接返回 0

以下为有名管道代码实现,写进程不断获取终端输入,并写到有名管道上,读进程阻塞读取管道中数据,并将数据打印出来:
写进程代码实现:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h> 
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#define FIFO_NAME "fifo"
int main()
{
	int fd = 0;
	int ret = 0;
	char buffer[1024] = {0};
	
	if(access(FIFO_NAME,F_OK) == -1)
	{
		ret = mkfifo(FIFO_NAME,0755);
		if(ret != 0)
		{
			printf("mkfifo err!\n");
			return -1;
		}
	}
	
	printf("mkfifo success,open O_WRONLY!\n");
	
	fd = open(FIFO_NAME,O_WRONLY);
	if(fd < 0)
	{
		printf("open FIFO_NAME fail!\n");
		return -1;
	}
	else
	{
		while(1)
		{
			gets(buffer);
			//strcpy(buffer,"hello nihao\n");
			ret = write(fd,buffer,strlen(buffer));
			if(-1 == ret )
			{
				printf("write buffer fail!\n");
				return -1;
			}
			memset(buffer,0,sizeof(buffer));
			sleep(1);
		}
		
	}
	
	close(fd);
	return 0;
}

读进程代码实现:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h> 
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#define FIFO_NAME "fifo"
int main()
{
	int fd = 0;
	int ret = 0;
	char buffer[1024] = {0};
	 
	unlink(FIFO_NAME);
	ret = mkfifo(FIFO_NAME,0755);
	if(ret != 0)
	{
		printf("mkfifo err!\n");
		return -1;
	}

	
	printf("mkfifo success,open O_RDONLY!\n");
	
	fd = open(FIFO_NAME,O_RDONLY);
	printf("zusissiiii\n");
	if(fd < 0)
	{
		printf("open FIFO_NAME fail!\n");
		return -1;
	}
	else
	{
		while(1)
		{
			ret = read(fd,buffer,sizeof(buffer));
			if(-1 == ret )
			{
				printf("write buffer fail!\n");
				return -1;
			}
			printf("FIFO read buffer:%s\n",buffer);
			memset(buffer,0,sizeof(buffer));
			sleep(1);
		}
		
	}
	
	close(fd);
	return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Chiang木

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

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

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

打赏作者

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

抵扣说明:

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

余额充值