FIFO有名管道

说明

无名管道,它只能用于具有亲缘关系的进程之间,这就大大地限制了管道的使用。有名管道的出现突破了这种限制, 它可以使互不相关的两个进程实现彼此通信。

  • 该管道可以通过路径名来指出,并且在文件系统中是可见的。在建立了管道之后,两个进程就可以把它当作普通文件一样进行读写操作,使用非常方便。
  • 不过 FIFO 是严格地遵循先进先出规则的,对管道及 FIFO 的读总是从开始处返回数据,对它们的写则把数据添加到末尾,它们不支持如 lseek()等文件定位操作。
  • 有名管道的创建可以使用函数 mkfifo(),该函数类似文件中的 open()操作,可以指定管道的路径和打开的模式
  • 在创建管道成功之后,就可以使用 open()、 read()和 write()这些函数了。与普通文件的开发设置一样,对于为读而打开的管道可在 open()中设置 O_RDONLY,
  • 对于为写而打开的管道可在 open()中设置 O_WRONLY,在这里与普通文件不同的是阻塞问题。由于普通文件的读写时不会出现阻塞问题,而在管道的读写中却有阻塞的可能,
  • 这里的非阻塞标志可以在 open()函数中设定为 O_NONBLOCK。下面分别对阻塞打开和非阻塞打开的读写进行讨论。
  • (1)对于读进程。
  •   若该管道是阻塞打开,且当前 FIFO 内没有数据,则对读进程而言将一直阻塞到有数据写入。
    
  •   若该管道是非阻塞打开,则不论 FIFO 内是否有数据,读进程都会立即执行读操作。即如果 FIFO内没有数据,则读函数将立刻返回 0。
    
  • (2)对于写进程。
  •   若该管道是阻塞打开,则写操作将一直阻塞到数据可以被写入。
    
  •   若该管道是非阻塞打开而不能写入全部数据,则读操作进行部分写入或者调用失败
    

函数

函数原型 int mkfifo(const char *filename,mode_t mode)

  • 函数传入值 filename:要创建的管道名字(包含路径)
  • 函数传入值 mode:
  •   O_RDONLY:读管道
    
  •   O_WRONLY:写管道
    
  •   O_RDWR:读写管道
    
  •   O_NONBLOCK:非阻塞
    
  •   O_CREAT:如果该文件不存在,那么就创建一个新的文件,并用第三个参数为其设置权限
    
  •   O_EXCL:如果使用 O_CREAT 时文件存在,那么可返回错误消息。这一参数可测试文件是否存在
    
  • 函数返回值:
  •   0:成功
    
  •   EACCESS:参数 filename 所指定的目录路径无可执行的权限
    
  •   EEXIST:参数 filename 所指定的文件已存在
    
  •   ENAMETOOLONG:参数 filename 的路径名称太长
    
  •   ENOENT:参数 filename 包含的目录不存在
    
  •   ENOSPC:文件系统的剩余空间不足
    
  •   ENOTDIR:参数 filename 路径中的目录存在但却非真正的目录
    
  •   EROFS:参数 filename 指定的文件存在于只读文件系统内
    

流程

在这里插入图片描述

实现

fifi_read.c

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

#define MYFIFO "/tmp/myfifo"
#define MAX_BUFFER_SIZE PIPE_BUF

int main(int argc,char * argv[])
{
	char buff[MAX_BUFFER_SIZE];
   	int fd;
	int nread;

    /* 判断有名管道是否已存在,若尚未创建,则以相应的权限创建*/
    if (access(MYFIFO, F_OK) == -1)
    {
        if ((mkfifo(MYFIFO, 0666) < 0) && (errno != EEXIST))
        {
            printf("Cannot create fifo file\n");
            exit(1);
        }
    }
	
	 /* 以只读阻塞方式打开有名管道 */
    fd = open(MYFIFO, O_RDONLY);
    if (fd == -1)
    {
        printf("Open fifo file error\n");
        exit(1);
    }
	
	/*循环读取有名管道数据*/
	while(1)
	{

		memset(buff, 0, sizeof(buff));

		if ((nread = read(fd, buff, MAX_BUFFER_SIZE)) > 0)
		{

			printf("Read '%s' from FIFO\n", buff);
		}
	}
	
    close(fd);
	exit(0);
}

fifi_write.c

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

#define MYFIFO "/tmp/myfifo"
#define MAX_BUFFER_SIZE PIPE_BUF

int main(int argc,char * argv[])
{
	char buff[MAX_BUFFER_SIZE];
   	int fd;
	int nwrite;
	
	if(argc<=1)
	{
		printf("Usage: ./fifo_write string\n");
		exit(1);
	}
	
	sscanf(argv[1],"%s",buff);

	 /* 以只写阻塞方式打开 FIFO 管道 */
    fd = open(MYFIFO, O_WRONLY);
	
    if (fd == -1)
    {
        printf("Open fifo file error\n");
        exit(1);
    }
	
	
    /*向管道中写入字符串*/
	if((nwrite = write(fd, buff, MAX_BUFFER_SIZE))>0)
	{
		printf("Write '%s' to FIFI\n",buff);
    }
   
	close(fd);
	exit(0);
}

现象

先打开读应用程序,再打开写应用程序
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值