wKioL1ZuVnLBMqY9AADMXNaTmIA629.png


管道是Linux支持的最初Unix IPC形式之一。

管道是半双工的,数据只能向一个方向流动;

一个管道只能负责一个方向的数据传输。

需要双方通信时,需要建立起两个管道;

只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);


假如进程A与进程b通信,需要建立两个管道:

wKioL1ZuU43DiTnSAABtEy-RtXk920.png


一个管道只能用于一个方向的通信,其另外的方向需要关闭.

wKioL1ZuVCThFv6YAABlqIm8eWA392.png


所以,假如A为父进程,B为子进程,那么父进程需关闭:
    void	CloseInParent(void)
    {
        m_Comm[0].closeReadHandle();
        m_Comm[1].closeWriteHandle();
    }

子进程需要关闭:

    void CloselnSub(void)

    {

        m_Comm[0].closeWriteHandle();

        m_Comm[1].closeReadHandle();

    }



父进行进行读取需要的handle,即A需要的:

    SOCKET getParentReadHandle(void) { return m_Comm[1].getReadHandle(); }

    SOCKET getParentWriteHandle(void) { return m_Comm[0].getWriteHandle(); }



子进程进行读取需要的handle,即B需要的:

    SOCKET getSubReadHandle(void) { return m_Comm[0].getReadHandle(); }

    SOCKET getSubWriteHandle(void) { return m_Comm[1].getWriteHandle(); }


对Unix网络编程-进程通信书里管道例子进行编码,两个进程,子进程发文件名给父进程,父进程返回子进程文件内容:


头文件

#ifndef CPIPE_H
#define CPIPE_H

#include <cstddef>
#define  SOCKET int
#define INVALID_SOCKET (SOCKET)(~0)
class  YPipe
{
public:
    YPipe(void);
    ~YPipe(void) { close(); }

    bool	open(bool boCanbeInherit = false);
    void	close(void) { closeReadHandle(); closeWriteHandle(); }

    int		read(void * lpBuff,size_t nLength);
    int		write(const void * lpBuff,size_t nLength);

    SOCKET	getReadHandle(void)  const { return m_nPipe[READHANDLE_INDEX]; }
    SOCKET	getWriteHandle(void)  const { return m_nPipe[WRITEHANDLE_INDEX]; }

    void	closeReadHandle(void) { closeImp(READHANDLE_INDEX); }
    void	closeWriteHandle(void) { closeImp(WRITEHANDLE_INDEX); }
protected:
    enum
    {
        READHANDLE_INDEX	=	0,
        WRITEHANDLE_INDEX	=	1,
    };
    void	closeImp(int nIndex);
    SOCKET		m_nPipe[2];
};

class YPipePair
{
public:
    YPipePair(void);
    ~YPipePair(void);

    bool	initEx(void);
    void	close(void)
    {
        m_Comm[0].close();
        m_Comm[1].close();
    }

    void	CloseInParent(void)
    {
        m_Comm[0].closeReadHandle();
        m_Comm[1].closeWriteHandle();
    }

    void	CloselnSub(void)
    {
        m_Comm[0].closeWriteHandle();
        m_Comm[1].closeReadHandle();
    }

    SOCKET		getParentReadHandle(void) { return m_Comm[1].getReadHandle(); }
    SOCKET		getParentWriteHandle(void) { return m_Comm[0].getWriteHandle(); }
    SOCKET		getSubReadHandle(void) { return m_Comm[0].getReadHandle(); }
    SOCKET		getSubWriteHandle(void) { return m_Comm[1].getWriteHandle(); }
protected:
    enum
    {
        MASTER_2_SUBMGR = 0x00,
        SUBMGR_2_MASTER = 0x01,
    };
    YPipe	m_Comm[2];
};
#endif // CPIPE_H

 

//源文件



#include "cpipe.h"
#include <unistd.h>

YPipe::YPipe(void)
{
    m_nPipe[0] = INVALID_SOCKET;
    m_nPipe[1] = INVALID_SOCKET;
}


void YPipe::closeImp(int nIndex)
{
    if (m_nPipe[nIndex] != INVALID_SOCKET)
        ::close(m_nPipe[nIndex]);
    m_nPipe[nIndex] = INVALID_SOCKET;
}

bool YPipe::open(bool boCanbeInherit)
{
    if (pipe(m_nPipe) == -1)
        return false;

//	m_nPipe[0] = CMX_Network_Function::checkAndChangeSocketID(m_nPipe[0]);
//	m_nPipe[1] = CMX_Network_Function::checkAndChangeSocketID(m_nPipe[1]);
    return true;
}

int	YPipe::read(void * lpBuff,size_t nLength)
{
    if (m_nPipe[READHANDLE_INDEX] == INVALID_SOCKET)
        return -1;
    return ::read(m_nPipe[READHANDLE_INDEX],lpBuff,nLength);
}

int	YPipe::write(const void * lpBuff,size_t nLength)
{
    if (m_nPipe[WRITEHANDLE_INDEX] == INVALID_SOCKET)
        return -1;
    return ::write(m_nPipe[WRITEHANDLE_INDEX],lpBuff,nLength);
}


YPipePair::YPipePair(void)
{
}

YPipePair::~YPipePair(void)
{
}



bool YPipePair::initEx(void)
{
    YPipePair::close();

    if (!m_Comm[SUBMGR_2_MASTER].open())
        return false;
    else if (!m_Comm[MASTER_2_SUBMGR].open())
        return false;

}

main.cpp

#include "cpipe.h"
#include <sys/types.h>
#include <unistd.h>
#include <string>
#include <sys/stat.h>;
#include <fcntl.h>;
#include<sys/wait.h>
#include   <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <iostream>
void jobInSub(YPipePair &tp)
{
    std::string strPath = "/home/cmy3/test.txt\n";

    int a = write(tp.getSubWriteHandle(), strPath.c_str(), strPath.size());

    char buf[1024];
    int n = 0;
    while ( ( n =read(tp.getSubReadHandle(),buf, 1024) )>0 ) //对方的写管道close的时候,才会返回0,所以对方记得要close
    {
        write(STDOUT_FILENO,buf, n);
    }

}
void jobInParent(YPipePair &tp)
{
    char buf[1024];
    int n;
    n =read(tp.getParentReadHandle(),buf, 1024)  ;
    buf[n]='\0';

    int fileFd;
    std::string strPath = "/home/cmy3/test.txt";
    if( (fileFd = open(strPath.c_str(), O_RDONLY))<0 )
    {
        snprintf(buf+n,sizeof(buf)-n, ":cannot open,%s\n", strerror(errno));
        n=strlen(buf);
        write(tp.getParentWriteHandle(), buf, n);
    }
    else
    {

        while ( ( n =read(fileFd,buf, 1024) )>0 )
        {
            write(tp.getParentWriteHandle(),buf, n);
        }
        close(fileFd);
    }
    tp.close(); //记得要close
//    ::close( tp.getParentWriteHandle() ); //记得要close
}
int main(int argc, char *argv[])
{
    YPipePair tp;
    tp.initEx();
    int forkPid;
    if( (forkPid = fork() )==0) //child
    {
        tp.CloselnSub();
        jobInSub(tp);   //send the filepath to parent ,and recv the file content
        exit(0); //must exit , if not ,go ahead
    }
    tp.CloseInParent();
    jobInParent(tp);  //recv the filepath from sub, and send the file content

    waitpid(0, NULL, 0);
    std::cout<<"exitparent"<<std::endl;
    exit(0);
    return 0;
}