Linux命名管道的创建及应用

目录

一、命名管道的定义即功能

1.1创建命名管道

1.2匿名管道和命名管道的区别

1.3命名管道的打开规则

二、进程间命名管道的创建及使用

2.1Comm.hhp

2.2PipeServer.cc

2.3PipeClient.cc


一、命名管道的定义即功能

管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。
如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。
命名管道是一种特殊类型的文件。

匿名管道只能通过fork的方式来实现父子两个进程之间的通信,而命名管道则是可以让仁义两个进程间实现通信 ,其底层原理为让两个进程打开同一个文件,一个读一个写从而实现通信的功能,当然此文件并不是真的在磁盘中创建了一个文件而是在内存中开辟了一块缓冲区而已。

而打开同一个文件就需要找到文件,即文件的路径+文件名。而通过文件名加路径的管道就是命名管道。

1.1创建命名管道

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

$ mkfifo filename

 

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

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

此时就可以看到一个开头为p的管道文件。此时就可以打开两个窗口,一边往里写一边往里读

而系统调用的mkfifo需要两个参数pathname表示要创建文件的文件名,mode则是默认权限。

创建命名管道:
int main(int argc, char *argv[])
{
 mkfifo("p2", 0644);
 return 0;
}

1.2匿名管道和命名管道的区别

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

1.3命名管道的打开规则

如果当前打开操作是为读而打开FIFO时
O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO
O_NONBLOCK enable:立刻返回成功
如果当前打开操作是为写而打开FIFO时
O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO
O_NONBLOCK enable:立刻返回失败,错误码为ENXIO

如果想要在代码中删除文件可以调用unlink来进行删除操作。 0返回表示成功,-1表示失败,错误码被设置。

二、进程间命名管道的创建及使用

2.1Comm.hhp

Comm.hpp包含了文件操作所需要的头文件以及常用头文件,包含了Fifo的管道类,可以实现管道的创建及命名,以及在进程结束时及时调用析构函数来对管道进行清理回收。

#ifndef __COMM_HPP__
#define __COMM_HPP__

//头文件
#include <cstring>
#include <string>
#include <cerrno>
#include <iostream>
//调用fifo所需的头文件+opean用到的头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>//open
//调用unlink对管道进行析构的头文件
#include <unistd.h>
//define
#define Mode 0666
#define Path "./fifo"
using namespace std;

class Fifo
{
public:
    Fifo(const string &path):_path(path)//创建有名管道
    {
        umask(0);
        int n=mkfifo(_path.c_str(),Mode);
        if(n==0)
        {
            cout<<"mkfifo sucess"<<endl;
        }
        else
        {
            cerr<<"mkfifo failed,errno: "<<errno<<",errstring: "<<strerror(errno)<<endl;
        }
    }
    ~Fifo()
    {
        int n=unlink(_path.c_str());//删除管道
        if(n==0)
        {
            cout<<"remove fifo file "<<_path<<"sucess"<<endl;
        }
        else
        {
            cerr<<"remove failed,errno: "<<errno<<",errstring: "<<strerror(errno)<<endl;
        }
    }
private:
    string _path;//有名管道的文件路径+文件名
};


#endif

2.2PipeServer.cc

服务器端负责创建管道并以读方式open打开:

pipeserver负责创建有名管道fifo并且以读方式进行打开,打开后会发出打开成功的信号,然后等待pipeclient往管道内部写入内容后将其读出以此来达到进程间通信的效果,如果client输入quit则一同退出。

pipeserver就类似于服务器一类的角色,负责创建通信工具和用于接收内容并进行反馈。

#include "Comm.hpp"
#include <unistd.h>

int main()
{
    Fifo fifo(Path);//定义管道文件fifo

    int rfd=open(Path,O_RDONLY);
    if(rfd<0)
    {
        cerr<<"open failed,errno: "<<errno<<",errstring: "<<strerror(errno)<<std::endl;
        return 1;
    }
    //如果我们的写端没有打开,先读端打开,open就会阻塞,直到把写端打开,读open才会返回
    cout<<"open sucess"<<endl; 
    char buffer[1024];
    while(true)
    {
        ssize_t n=read(rfd,buffer,sizeof(buffer)-1);//文件读的时候不需要考虑/0所以sizeof-1
        if(n>0)
        {
            buffer[n]=0;//将最后一位变为0
            cout<<"client say: "<<buffer<<endl;
        }
        else if(n==0)
        {
            cout<<"client quit,me too bye bye"<<std::endl;
            break;
        }
        else
        {
            cerr<<"read failed,errno: "<<errno<<",errstring: "<<strerror(errno)<<endl;
            break;
        }
    }
    close(rfd);
    return 0;
}

2.3PipeClient.cc

pipeclient则就是供用户进行使用的端口,使用端以写方式打开管道文件,并且负责向管道内部写入数据以及内容,然后由服务器进行读取。

#include "Comm.hpp"

int main()
{
    int wfd=open(Path,O_WRONLY);
    if(wfd<0)
    {
        cerr<<"open failed,errno: "<<errno<<",errstring"<<strerror(errno)<<std::endl;
        return 1;
    }
    string inbuffer;
    while(true)
    {
        cout<<"Please Enter Your Message#";
        getline(cin,inbuffer);
        if(inbuffer=="quit") break;
        ssize_t n=write(wfd,inbuffer.c_str(),inbuffer.size());
        if(n<0)
        {
            cerr<<"write failed,errno: "<<errno<<",errstring: "<<strerror(errno)<<std::endl;
            break;
        }
    }
    close(wfd);
    return 0;
}

  • 22
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C+五条

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值