进程间通信--命名管道

命名管道

命名管道是一个存在于文件系统的一个特殊文件,
命名管道和匿名管道区别:

  • 命名管道FIFO是存在与文件系统中的特殊文件,其内容仍然存在于内存中
  • 命名管道因为有名字存在文件系统中,因此可以实现任意进程间通信
  • 使用FIFO的进程退出后,FIFO文件会继续存在文件系统中可以重新使用
创建命名管道

从命令行创建:mkfifo filename
在程序中创建:
函数原型: int mkfifo( const char *filename, mode_t mode);
返回值:成功返回0, 如果文件已经存在返回-1errno为EEXIST
参数:filename 需要创建的管道文件名 mode FIFO文件权限

命名管道操作

命名管道创建成功后和普通文件一样进行操作,打开后命名管道默认属性是阻塞
读写规则:
阻塞状态下
open() 以只读方式打开 FIFO 时,要阻塞到某个进程为写而打开此 FIFO
open() 以只写方式打开 FIFO 时,要阻塞到某个进程为读而打开此 FIFO。

阻塞状态下 写端关闭后读端读取数据 写端开启读端读取数据 读端关闭后写端写数据 读端开启写端写数据
管道无数据 返回0 阻塞 收到SIGPIPE信号 写入数据返回实际写入数据的字节数
管道有数据 读取数据并返回实际读取的字节数 读取数据并返回实际读取的字节数 收到SIGPIPE信号 如果管道已满就阻塞,否则返回实际写入数据的字节数

非阻塞状态下
open() 以只读方式打开 FIFO 时,直接返回成功
open() 以只写方式打开 FIFO 时,返回失败( -1 ) errno 为ENXIO

非阻塞状态 写端关闭后读端读取数据 写端开启读端读取数据 读端关闭后写端写数据 读端开启写端写数据
管道无数据 返回0 返回-1 errno 为EAGAIN 收到SIGPIPE信号 写入数据返回实际写入数据的字节数
管道有数据 读取数据并返回实际读取的字节数 读取数据并返回实际读取的字节数 收到SIGPIPE信号 如果管道已满直接返回0,否则返回实际写入数据的字节数

用命名管道实现文件的拷贝

从text文件读取数据写入管道

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
 
#define ERR_EXIT(m) \
    do      \
    {       \
        perror(m);\
        exit(EXIT_FAILURE);\
    }while(0)

int main()
{
    if(mkfifo("tp", 0666) < 0 && (errno != EEXIST))
        ERR_EXIT("cannot create fifo");

    int outfd = open("tp", O_WRONLY);
    if(outfd == -1)
        ERR_EXIT("open fifo error");
    
    int infd = open("text", O_RDONLY);
    if(infd == -1)
        ERR_EXIT("open");

    char buff[1024] = { 0 };
    int num;
    while((num = read(infd, buff, 1023)) > 0)
    {
        write(outfd, buff, num);
    }
    close(infd);
    close(outfd);
    return 0;
}

从管道读取数据写入文件text.ba中

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
 
#define ERR_EXIT(m) \
    do      \
    {       \
        perror(m);\
        exit(EXIT_FAILURE);\
    }while(0)

int main()
{
    if(mkfifo("tp", 0666) < 0 && (errno != EEXIST))
        ERR_EXIT("cannot create fifo");

    int infd = open("tp", O_RDONLY);
    if(infd == -1) 
        ERR_EXIT("open fifo error");
                                                               
    int outfd = open("text.ba", O_WRONLY|O_CREAT|O_TRUNC, 0644);
    if(outfd == -1)
        ERR_EXIT("open");

    char buff[1024] = { 0 };
    int num;
    while((num = read(infd, buff, 1023)) > 0)
    {
        write(outfd, buff, num);
    }
    close(outfd);
    close(infd);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Jocker_D/article/details/83957066