Linux下的IPC通信,linux-IPC进程通信-管道

f955ebb38ef5d167bf95938fba83993e.png

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

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

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

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

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

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

81cd853f1e17263c7dc5f8c7fc8cadd2.png

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

4f1a0144bf03803fa46765447680464e.png所以,假如A为父进程,B为子进程,那么父进程需关闭:

voidCloseInParent(void)

{

m_Comm[0].closeReadHandle();

m_Comm[1].closeWriteHandle();

}

子进程需要关闭:

voidCloselnSub(void)

{

m_Comm[0].closeWriteHandle();

m_Comm[1].closeReadHandle();

}

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

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

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

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

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

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

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

头文件#ifndef CPIPE_H

#define CPIPE_H

#include 

#define  SOCKET int

#define INVALID_SOCKET (SOCKET)(~0)

class  YPipe

{

public:

YPipe(void);

~YPipe(void) { close(); }

boolopen(bool boCanbeInherit = false);

voidclose(void) { closeReadHandle(); closeWriteHandle(); }

intread(void * lpBuff,size_t nLength);

intwrite(const void * lpBuff,size_t nLength);

SOCKETgetReadHandle(void)  const { return m_nPipe[READHANDLE_INDEX]; }

SOCKETgetWriteHandle(void)  const { return m_nPipe[WRITEHANDLE_INDEX]; }

voidcloseReadHandle(void) { closeImp(READHANDLE_INDEX); }

voidcloseWriteHandle(void) { closeImp(WRITEHANDLE_INDEX); }

protected:

enum

{

READHANDLE_INDEX=0,

WRITEHANDLE_INDEX=1,

};

voidcloseImp(int nIndex);

SOCKETm_nPipe[2];

};

class YPipePair

{

public:

YPipePair(void);

~YPipePair(void);

boolinitEx(void);

voidclose(void)

{

m_Comm[0].close();

m_Comm[1].close();

}

voidCloseInParent(void)

{

m_Comm[0].closeReadHandle();

m_Comm[1].closeWriteHandle();

}

voidCloselnSub(void)

{

m_Comm[0].closeWriteHandle();

m_Comm[1].closeReadHandle();

}

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

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

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

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

protected:

enum

{

MASTER_2_SUBMGR = 0x00,

SUBMGR_2_MASTER = 0x01,

};

YPipem_Comm[2];

};

#endif // CPIPE_H

//源文件#include "cpipe.h"

#include 

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;

}

intYPipe::read(void * lpBuff,size_t nLength)

{

if (m_nPipe[READHANDLE_INDEX] == INVALID_SOCKET)

return -1;

return ::read(m_nPipe[READHANDLE_INDEX],lpBuff,nLength);

}

intYPipe::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 

#include 

#include 

#include ;

#include ;

#include

#include   

#include 

#include 

#include 

#include 

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<

exit(0);

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值