【Linux】命名管道的创建方法&&基于命名管道的两个进程通信的实现

2024-04-15 08:10:17 浏览数 (1)

一、匿名管道和命名管道的区别

  • 匿名管道由pipe函数创建并打开。
  • 命名管道由mkfifo函数创建,打开用open
  • FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完成之后,它们具有相同的语义。

一、创建命名管道的函数

代码语言:javascript复制
 #include <sys/stat.h>
 // 返回值:成功返回0,出错返回-1
 int mkfifo(const char *pathname, mode_t mode);

pathname指创建出来的管道的路径和管道名,mode指创建出来的管道的权限,这里的权限和文件的权限是一样的。

二、删除命名管道的函数

代码语言:javascript复制
 #include <unistd.h>
 // 返回值:成功返回0,出错返回-1
 int unlink(const char *pathname);

pathname指创建出来的管道的路径和管道名,unlink也可以用来删除一般的文件。

三、利用命名管道实现两个进程之间的简单通信

 这个通信将实现写端发送信息读端接收信息。更多地实现细节会在代码中以注释的方式给出。

3.1、头文件

代码语言:javascript复制
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <cstdio>

using namespace std;

#define MODE 0666 //权限
#define NAME "./fifo.txt"

//定义命名管道结构体
class Fifo
{
private:
    string _name; // 文件路径加文件名
public:
    Fifo(const string &name)
        : _name(name)
    {
        int n = mkfifo(_name.c_str(), MODE);

        if (n == 0)
            cout << "创建管道成功!" << endl;
        else
            cout << "创建管道失败!原因是:" << strerror(errno) << endl;
    };
    ~Fifo()
    {
        int n = unlink(_name.c_str());

        if (n == 0)
            cout << "删除管道成功!" << endl;
        else
            cout << "删除管道失败!原因是:" << strerror(errno) << endl;
    };
};

3.2、接收方(Server)

代码语言:javascript复制
#include "namedPipe.hpp"

int main()
{

    Fifo fifo(NAME);
    //打开文件,打开成功返回文件描述符,打开失败返回-1
    int rfd = open(NAME, O_RDONLY);
    if (rfd < 0)
    {
        cout << "文件打开失败,原因是:" << strerror(errno) << endl;
        return 1;
    }
    cout << "文件打开成功!" << endl;

    while (true)
    {
        char buffer[1024];
        //读端不退,read函数会一直阻塞等待,读端退出read读到0
        ssize_t n = read(rfd, buffer, sizeof(buffer) - 1);

        if (n > 0)
        {
            buffer[n] = '';
            cout << "客户说:" << buffer << endl;
        }
        else if (n == 0)
        {
            cout << "客户退出了,我也退出了";
            break;
        }
        else
        {
            cout << "读取出错!原因是:" << strerror(errno) << endl;
            break;
        }
    }

    close(rfd);
    return 0;
}

3.3、发送方(Client)

代码语言:javascript复制
#include "namedPipe.hpp"

int main()
{
    int wfd = open(NAME, O_WRONLY);
    
    if (wfd < 0)
    {
        cout << "文件打开失败,原因是:" << strerror(errno) << endl;
        return 1;
    }
    cout << "文件打开成功!" << endl;

    string buffer;
    while(true)
    {
        cout << "请输入你的信息:" << endl;
        getline(cin, buffer);
        if(buffer == "quit")
        break;

        int n = write(wfd, buffer.c_str(), sizeof(buffer)-1);
        
        if(n < 0)
        {
            cout << "输入错误,错误原因是:" << strerror(errno) << endl;
        }

    }

    close(wfd);
    return 0;
}

0 人点赞