命名管道原理(和匿名管道的对比),mkfifo(命令行,函数),命名管道模拟实现代码+与多个子进程通信代码

目录

命名管道

引入

原理

和匿名管道的对比

使用 -- mkfifo

命令行指令

 创建

文件类型p

使用

函数

函数原型

模拟实现

头文件

客户端代码

服务端代码

运行情况

模拟实现 -- 与多个子进程

介绍

服务端代码: 

运行情况


命名管道

引入

匿名管道只能用于父子进程之间通信,如果我们想要两个完全无关联的进程通信该怎么办?

  • 首先,通信本质还是不变的 : 要让不同的进程看到同一份资源
  • 依然还是用文件作为中间介质,但拿到文件的方式不同

原理

  • 如果一个进程打开一个文件,另一个进程也想打开这个文件:
  • 直接让该进程也指向这个已存在的file结构体(不需要再创建一个file,否则内存中会存在大量相同的数据)

  • 但是!普通文件的数据是要被刷新到磁盘上的
  • 我们的目的可不是为了将数据写到磁盘,而是让两个进程进行通信
  • 因此需要尽量避免io(1是 io速度太慢,2是 通信过程产生的数据没必要写到磁盘上)
  • 因此,管道文件油然而生(也就是命名管道),它是一种特殊的文件
  • 它一旦被打开,就会有自己的路径(路径具有唯一性)
  • 因此,不同进程就可以通过唯一的路径来访问同一个管道文件

和匿名管道的对比

两种管道本质上都是一样的(都是文件) 

实现[让不同进程看到同一份资源]的手段不同

  • 匿名管道 -- 子进程继承父进程的文件描述符表,[直接用fd拿到文件]
  • 命名管道 -- 两个进程访问同一路径下的文件,[用路径拿到文件]

使用 -- mkfifo

命令行指令

命名管道原理(和匿名管道的对比),mkfifo(命令行,函数),命名管道模拟实现代码+与多个子进程通信代码_第1张图片

 创建

命名管道原理(和匿名管道的对比),mkfifo(命令行,函数),命名管道模拟实现代码+与多个子进程通信代码_第2张图片

文件类型p

p(pipe) -- 管道文件

使用

当只有一个进程打开该管道时,会阻塞

两个不同进程打开同一路径的管道文件(一个命令就是一个进程 ,echo和cat)

就可以进行通信噜

函数

函数原型

命名管道原理(和匿名管道的对比),mkfifo(命令行,函数),命名管道模拟实现代码+与多个子进程通信代码_第3张图片

模拟实现

头文件

comm.hpp:

#ifndef COMM_H
#define COMM_H

#include 
#include 
#include 
#include 
#include 
#include 
#include

using namespace std;

string pipe_path = "./fifo.ipc";
#define mode 0666
#define num 1024

#endif

log.hpp:

#pragma once

#include 
#include 
#include

using namespace std;

#define debug 0
#define notice 1
#define warning 2
#define error 3

const string msg[]  //定义不同类型的信息状态
{
    "debug", "notice", "warning", "error"
};

ostream& log(string message,int level) { 
    cout<<"|"<<(unsigned)time(nullptr)<<"|"<

客户端代码

#include"comm.hpp"

//用于发送信息(客户端)
int main(){
    //文件操作
    int fd=open(pipe_path.c_str(),O_WRONLY|O_TRUNC);
    if(fd<0){
        perror("open");
        exit(1);
    }
    string buffer;
    while(true){
        cout<<"Please enter the information you want to send : "<

服务端代码

#include "comm.hpp"
#include"log.hpp"

// 用于接收信息(服务端)

int main()
{
    // 创建管道文件
    if (mkfifo(pipe_path.c_str(), mode) < 0)
    {
        perror("mkfifo");
    }
    log("创建管道文件成功",debug);

    // 文件操作
    int fd = open(pipe_path.c_str(), O_RDONLY);
    if (fd < 0)
    {
        perror("open");
        exit(1);
    }
    log("打开文件成功",debug);

    // 进行通信
    char buffer[num];
    while (true)
    {
        memset(buffer, 0, sizeof buffer);
        ssize_t size = read(fd, buffer, sizeof buffer - 1);//读取管道文件中的内容
        cout<

运行情况

创建管道,等待另一方打开该管道

一端打开文件后,另一端才打开

服务端收到客户端发送的信息

客户端关闭,服务端也退出命名管道原理(和匿名管道的对比),mkfifo(命令行,函数),命名管道模拟实现代码+与多个子进程通信代码_第4张图片当服务端关闭,客户端也会退出命名管道原理(和匿名管道的对比),mkfifo(命令行,函数),命名管道模拟实现代码+与多个子进程通信代码_第5张图片

 

模拟实现 -- 与多个子进程

介绍

  • 其他部分与上面相同,只需要在服务端修改
  • 将读取信息的部分分装一个函数
  • 然后在服务端创建子进程,让子进程去读取客户端发送的信息

服务端代码: 

#include "comm.hpp"
#include"log.hpp"

// 用于接收信息(服务端)

void recive_message(int fd){
    char buffer[num];
    while (true)
    {
        memset(buffer, 0, sizeof buffer);
        ssize_t size = read(fd, buffer, sizeof buffer - 1);
        //cout<

运行情况

命名管道原理(和匿名管道的对比),mkfifo(命令行,函数),命名管道模拟实现代码+与多个子进程通信代码_第6张图片

你可能感兴趣的:(linux,c,c++,算法,开发语言)