• _linux 进程间通信(命名管道)


    1. 创建一个命名管道

    • 命名管道可以从命令行上创建,命令行方法是使用下面这个命令。

      $ mkfifo filename
      
      • 1

      在这里插入图片描述
      上图可见进程间通信成功。

    • 命名管道也可以从程序里创建,相关函数有

      int mkfifo(const char *filename,mode_t mode);
      
      • 1

      查手册:

      man 3 mkfifo
      
      • 1

      在这里插入图片描述

    2. 用命名管道实现server&client通信

    2.0 log.hpp打印日志信息

    #ifndef _LOG_H_
    #define _LOG_H_
    
    #include 
    #include 
    
    enum e
    {
        Debug,
        Notice,
        Warning,
        Error
    };
    
    const std::string msg[]{
        "Debug",
        "Notice",
        "Warning",
        "Error"};
    
    std::ostream &log(std::string message, int level)
    {
        std::cout << " | " << (unsigned)time(nullptr) << " | " << msg[level] << " | " << message;
        return std::cout;
    }
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    2.1 comm.hpp(server.cc和client.cc共有文件)

    #ifndef _COMM_H_
    #define _COMM_H
    
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    
    #define MODE 0666
    #define SIZE 128
    string ipcpath = "./fifo.ioc";
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2.2 server.cc读取数据

    #include "comm.hpp"
    #include "log.hpp"
    int main()
    {
        // 1. 创建管道文件
        if (mkfifo(ipcpath.c_str(), MODE) < 0)
        {
            perror("mkfifo");
            exit(1);
        }
    
        log("创建管道文件成功", Debug) << " step 1" << endl;
    
        // 2. 正常的文件操作
        int fd = open(ipcpath.c_str(), O_RDONLY);
        if (fd < 0)
        {
            perror("open");
            exit(2);
        }
    
        log("打开管道文件成功", Debug) << " step 2" << endl;
    
        // 3. 编写正常代码
        char buffer[SIZE];
        while (true)
        {
            ssize_t s = read(fd, buffer, sizeof(buffer) - 1);
            if (s > 0)
            {
                cout << "[" << getpid() << "]"
                     << "client say " << buffer << endl;
            }
            else if (s == 0)
            {
                // end of file
                cerr << "[" << getpid() << "]"
                     << "read end of file, client quit, server quit too!" << endl;
                break;
            }
            else
            {
                // read error
                perror("read");
                exit(3);
                break;
            }
        }
        // 4. 关闭文件
        close(fd);
        log("关闭管道文件成功", Debug) << " step 3" << endl;
    
        unlink(ipcpath.c_str()); //通信完毕,就删除文件
        log("删除管道文件成功", Debug) << " step 4" << endl;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    2.3 client.cc发送数据

    #include "comm.hpp"
    
    int main()
    {
        // 1. 获取管道文件
        int fd = open(ipcpath.c_str(), O_WRONLY);
        if (fd < 0)
        {
            perror("open");
            exit(1);
        }
    
        // 2. ipc过程
        string buffer;
        while (true)
        {
            cout << "请输入一行信息 :> ";
            getline(cin, buffer);
            write(fd, buffer.c_str(), buffer.size());
        }
    
        // 3. 关闭
        close(fd);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    2.4 结果展示

    在这里插入图片描述

    3. 还可以多个进程接收

    • client.cc
    #include "comm.hpp"
    #include "log.hpp"
    #include 
    static void getMessag(int fd)
    {
        char buffer[SIZE];
        while (true)
        {
            ssize_t s = read(fd, buffer, sizeof(buffer) - 1);
            if (s > 0)
            {
                cout << "[" << getpid() << "]"
                     << "client say " << buffer << endl;
            }
            else if (s == 0)
            {
                // end of file
                cerr << "[" << getpid() << "]"
                     << "read end of file, client quit, server quit too!" << endl;
                break;
            }
            else
            {
                // read error
                perror("read");
                exit(3);
                break;
            }
        }
    }
    int main()
    {
        // 1. 创建管道文件
        if (mkfifo(ipcpath.c_str(), MODE) < 0)
        {
            perror("mkfifo");
            exit(1);
        }
    
        log("创建管道文件成功", Debug) << " step 1" << endl;
    
        // 2. 正常的文件操作
        int fd = open(ipcpath.c_str(), O_RDONLY);
        if (fd < 0)
        {
            perror("open");
            exit(2);
        }
    
        log("打开管道文件成功", Debug) << " step 2" << endl;
    
        for (int i = 0; i < 3; i++)
        {
            pid_t id = fork();
            if (id == 0)
            {
                // 3. 编写正常代码
                getMessag(fd);
                exit(0);
            }
        }
        for (int i = 0; i < 3; i++)
        {
            waitpid(-1, nullptr, 0);
        }
        // 4. 关闭文件
        close(fd);
        log("关闭管道文件成功", Debug) << " step 3" << endl;
    
        unlink(ipcpath.c_str()); //通信完毕,就删除文件
        log("删除管道文件成功", Debug) << " step 4" << endl;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
  • 相关阅读:
    【gpt redis】原理篇
    Python武器库开发-高级特性篇(七)
    pg14安装_rpm方式
    摩尔定律的概念
    Hive安装与配置实战指南
    FFmpeg 常用API
    [PAT练级笔记] 06 Basic Level 1008
    https和http
    解决运行Pycharm中pip升级成功,但安装第三方包却未生效问题
    Arcgis提取每个像元的多波段反射率值
  • 原文地址:https://blog.csdn.net/Dingyuan0/article/details/128057197