命名管道详解

本文介绍了命名管道的基本概念,展示了如何在C++中创建和使用命名管道进行进程间通信,包括创建管道文件、客户端和服务端的数据交互以及管道操作的特性如阻塞和同步。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

命名管道

        命名管道,就是创建一个命名的管道文件,供进程间通信。

        命名管道与匿名管道的区别就在于使用命名管道可以在文件夹中看到创建出来的管道文件。

        匿名管道只能用于具有血缘关系的通信,而命名管道可以用于没有血缘关系的进程间通信。

1、创建命名管道

        使用mkfifo创建命名的管道文件。

        参数:pathname表示管道文件的路径名,mode表示创建管道文件的权限。

        返回值:成功返回 0;失败返回 -1,并设置错误码。

实验示例:

#include <iostream>
#include <string>
#include <error.h>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

using namespace std;

int main()
{
    // 在当前路径下创建管道文件,名字为fifo,权限为0666
    int ret = mkfifo("./fifo", 0666);

    return 0;
}

2、使用管道文件

        创建管道文件成功后,进程间通信就转化为了向管道写数据、向管道读数据。

        我们模拟客户端和服务端,客户端发数据,服务端读数据,测试命名管道。

服务端:a、负责创建管道文件以及删除管道文件。

              b、负责读取数据。

#include <iostream>
#include <string>
#include <error.h>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

using namespace std;

int main()
{
    // 创建命名管道
    int ret = mkfifo("./fifo", 0666);
    if(ret < 0)
    {
        printf("open fifo fail, errno is %d, errinfo is %s\n", errno, strerror(errno));
        return errno;
    }
    // 打开命名管道
    int rfd = open(Path, O_RDONLY);
    if (rfd < 0)
    {
        printf("open fifo fail, errno is %d, errinfo is %s\n", errno, strerror(errno));
    }
    printf("open success\n");
    // 读
    char buffer[1024];
    while (1)
    {
        // 从文件读取数据
        ssize_t n = read(rfd, buffer, sizeof(buffer) - 1);
        if (n > 0)
        {
            buffer[n] = '\0';
            cout << "server get a mseeage : " << buffer << endl;
        }
        else if (n == 0)
        {
            cout << "server quit..." << endl;
            break;
        }
        else
        {
            printf("read fifo fail, errno is %d, errinfo is %s\n", errno, strerror(errno));
        }
    }
    // 关闭管道
    close(rfd);

    // 删除命名管道
    unlink("./fifo");
    return 0;
}

客户端:负责输入数据,输入为 "quit" 时,关闭写端。

        当客户端关闭写端时,服务端就会读到0表示结尾,服务端就会关闭写端并删除文件。

#include <iostream>
#include <string>
#include <error.h>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

using namespace std;

int main()
{
    // 打开命名管道
    int rfd = open("./fifo", 0666);
    if (rfd < 0)
    {
        printf("open fifo fail, errno is %d, errinfo is %s\n", errno, strerror(errno));
    }
    // 写
    string str;
    while (1)
    {
        cout << "Please Enter Your Message:> ";
        getline(cin, str);
        // 如果用户输入quit,那就退出,然后关闭写端。
        if(str == "quit")
        {
            cout << "client quit..." << endl;
            break;
        }
        ssize_t n = write(rfd, str.c_str(), str.size());
        if (n > 0)
        {
            cout << "Send Your Message Successfully" << endl;
        }
        else if(n == 0)
        {
            continue;
        }
        else
        {
            printf("write fifo fail, errno is %d, errinfo is %s\n", errno, strerror(errno));
        }
    }

    // 关闭管道
    close(rfd);
    return 0;
}

 

3、总结

        管道都是基于文件的。

        1、当写端未关闭,读快写慢,当文件内没数据时,读端就会在read阻塞等待,写端写了再读

        2、当读端未关闭,写快读慢,写端就会一直写,直到写满,阻塞等读端读,然后再写。

        3、当写端关闭,读端就会读到0,表示读到结束。

        4、当读端关闭,如果写端还在写,会通过13信号杀死进程。

         5、在使用open时,先打开读端或写端中的任意一个,open()函数都会阻塞,只有读端和写端都打开了,才能正常运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值