linux管道进程通信,linux进程间通信-----管道总结实例

管道简介:

管道是进程之间通信的一种方式,就相当于是两个进程之间有一条地道,可以通过地道来传递信息;

管道位于进程的地址空间之外;管道分为匿名管道和命名管道两种;

匿名管道是由pipe来创建的,命名管道是由mkfifo来创建的;

#include

int pipe(int pipefd[2]);返回两个描述符:pipefd[0]是管道的读端,pipefd[1]是管道的写端;

#include

#include

int mkfifo(const char *pathname, mode_t mode)创建命名管道成功返回0;参数是一个pathname是创建的FIFO管道文件的名字;mode用户权限是标识位,比如是0644;

创建了一个管道文件之后,要用它和其它进程通信的时候需要再打开该文件open;

命名管道的打开规则

如果当前打开操作是为读而打开FIFO时

1:O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO

2:O_NONBLOCK enable:立刻返回成功

如果当前打开操作是为写而打开FIFO时

1:O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO

2:O_NONBLOCK enable:立刻返回失败,错误码为ENXIO

//outfd = open("fifop", O_WRONLY | O_NONBLOCK);//非阻塞写

outfd = open("fifop", O_WRONLY ); //阻塞模式

例如:

1:一个进程打开命名管道写,默认是阻塞的方式打开;如果该管道没有另外的进程打开读,则该进程阻塞在写打开,直到有进程读打开;

2:一个进程打开命名管道读,默认是阻塞的方式打开;如果该管道没有另外的进程打开写,则该进程阻塞在读打开,直到有进程写打开;

一般以阻塞方式打开,如果是以非阻塞方式打开的话,每次从该文件读取数据的时候会立刻返回,哪怕是没有数据;

命名管道和匿名管道区别:

1:管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。

2:如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。

3:命名管道是一种特殊类型的文件;

管道可以在父子进程之间传递数据

管道可以在父子进程之间传递数据,利用的是fork调用之后两个管道文件描述符pipefd[0]和pipefd[1]都保持打开。这样就可以实现父进程通过管道向子进程传递数据,或者子进程通过管道向父进程传递数据。

如果是想双向传输数据的话,可以创建两个管道。也可以通过socketpair创建一个全双工的管道。

例子1:父进程通过匿名和子进程通信,父进程向匿名管道写入数据,子进程从匿名管道读出数据并输出到标准输出上面

/*************************************************************************

> File Name: pipe1.cpp

> Author:

> Mail:

> Created Time: 2015年12月20日 星期日 19时48分57秒

************************************************************************/

#include

#include

#include

#include

#include

#include

#include

using namespace std;

/*

1:父进程创建一个管道, 0-read, 1-write

2:父进程创建一个子进程

3:让父进程向管道中写入信息,子进程从管道读取信息;从标准输入写入到管道中

4:子进程将读取的信息输出到标准输出上面

*/

int main()

{

int pipefd[2];

char buff[1024];

memset(buff, 0, 1024);

int ret = pipe(pipefd);

if(ret != 0){

cerr << "pipe error..." << endl;

exit(-1);

}

pid_t pid = fork();

if(pid < 0){

cerr << "fork error..." << endl;

exit(-1);

}

else if(pid == 0){

//关闭管道的写端

close(pipefd[1]);

int ret = 0;

cout << "This is child process...." << endl;

while(1){

ret = read(pipefd[0], (void *)buff, 1024);

if(ret == 0){

cout << "end of read.." << endl;

exit(0);

}

cout << "child read: ";

cout << buff << endl;

memset(buff, 0, 1024);

}

close(pipefd[0]);

}

else if(pid > 0){

close(pipefd[0]);

cout << "This is parent process...." << endl;

while(cin.getline(buff, 1024)){

cout << "parent write: ";

cout << buff << endl;

write(pipefd[1], buff, 1024);

memset(buff, 0, 1024);

}

close(pipefd[1]);

wait(NULL);

}

exit(0);

}

82a207b8e272520d862d8367f35e86ab.png

例子2:

进程1创建命名管道myfifo,并以阻塞方式写打开,进程1从标准输入获得数据并写入到命名管道中;

进程2以阻塞方式读打开该命名管道文件myfifo,进程2从该命名管道中读取数据并输出到标准输出上;

进程1:write_fifo.cpp

/*************************************************************************

> File Name: write_fifo.cpp

> Author:

> Mail:

> Created Time: 2015年12月20日 星期日 20时53分29秒

************************************************************************/

#include

#include

#include

#include

#include

#include

#include

using namespace std;

/*

1:创建命名管道

2:从标准输入输入内容到buffer中

3:打开命名管道,将buffer中的内容写入到命名管道中

*/

int main()

{

int ret = mkfifo("myfifo", 0666);

if(ret < 0){

cerr << "mkfifo error..." << endl;

exit(-1);

}

char buff[1024];

memset(buff, 0, 1024);

int wrfd;

cout << "wating for another process open the myfifo to reading..."<< endl;

wrfd = open("myfifo", O_WRONLY);

if(wrfd == -1){

cerr << "open error..." << endl;

exit(-1);

}

pid_t pid = getpid();

cout << "process " << pid << " write: ";

while(cin.getline(buff, 1024)){

write(wrfd, buff, strlen(buff));

memset(buff, 0, 1024);

cout << "process " << pid << " write: ";

}

close(wrfd);

exit(0);

}进程2:read_fifo.cpp

/*************************************************************************

> File Name: write_fifo.cpp

> Author:

> Mail:

> Created Time: 2015年12月20日 星期日 20时53分29秒

************************************************************************/

#include

#include

#include

#include

#include

#include

#include

using namespace std;

/*

1:创建命名管道

2:从标准输入输入内容到buffer中

3:打开命名管道,将buffer中的内容写入到命名管道中

*/

int main()

{

char buff[1024];

memset(buff, 0, 1024);

int rdfd;

int ret = 0;

rdfd = open("myfifo", O_RDONLY);

if(rdfd < 0){

cout << "open error..." << endl;

exit(-1);

}

cout << "waiting for reading...\n";

while(1){

ret = read(rdfd, buff, 1024);

if(ret == 0){

cerr << "end of read..." << endl;

break;

}

cout << "process "<< getpid() << " read: " << buff << endl;

memset(buff, 0, 1024);

}

close(rdfd);

exit(0);

}

04af84e54c7e46c5687c37f05356cd3f.png

下面图中的myfifo文件就是创建的命名管道,可以看到它的文件类型为p开头;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值