目录
一、只有血缘关系的进程之间才可以进行管道通信
二、管道只可以单向通信
三、进程间通信是会协同的-同步与互斥的
1.父子进程读写端都正常,管道为空父进程读端阻塞。
2.父子进程读写端都正常,管道满时子进程写端阻塞。
3.子进程写端关闭,父进程读端正常,父进程就会读到0,表明读到了管道文件的末尾,父进程读端不会被阻塞。(一般可利用这种情况间接的终止子进程)
4.子进程写端正常,父进程关闭读端,操作系统就会终止子进程(本质是OS通过发送信号终止掉)
四、管道通信是面向字节流的
五、管道是基于文件的,而文件的生命周期是随进程的
一、只有血缘关系的进程之间才可以进行管道通信
血缘关系如何理解呢?其实就是父进程fork创建了多个子进程,这些子进程之间的关系就是兄弟关系,子进程又创建了子进程,该子进程与第一个父进程就是爷孙关系了等等,一般是父进程和子进程之间进行通信的多。
二、管道只可以单向通信
三、进程间通信是会协同的-同步与互斥的
管道也是有固定大小的,当向管道被写满是则不能再继续向管道里写入内容!
进程间通过管道进行通信(子进程向管道写数据,父进程读数据)的4种情况:
1.父子进程读写端都正常,管道为空父进程读端阻塞。
2.父子进程读写端都正常,管道满时子进程写端阻塞。
3.子进程写端关闭,父进程读端正常,父进程就会读到0,表明读到了管道文件的末尾,父进程读端不会被阻塞。(一般可利用这种情况间接的终止子进程)
如下代码用于测试匿名管道特性1和特性3:
#include <iostream>
#include <unistd.h>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#define NUM 1024
char array[NUM]={0};
int pipefd[2]={0};
void Writer(int wpipe)
{
std::string s="hello pipe";
int cnt =5;
while(cnt>0)
{
array[0]=0;
snprintf(array, sizeof(array), "%s-%d", s.c_str(), cnt--);//构建向管道发送的字符串
write(wpipe, array, strlen(array));//向管道写入字符串内容
sleep(2);
}
}
void Reader(int rpipe)
{
while(true)
{
array[0]=0;
ssize_t n = read(rpipe, array, sizeof(array));
if(n>0)
{
array[n]=0;
std::cout<<"parent get news from pipe is:"<< array <<std::endl;
}
else if(0==n)
break;
}
}
int main()
{
int tmp = pipe(pipefd);//父进程创建管道文件
assert(!tmp);
pid_t rid = fork();
if(0 == rid)//child 子进程向管道写内容
{
close(pipefd[0]);
Writer(pipefd[1]);
exit(0);
}
close(pipefd[1]);//parent
Reader(pipefd[0]);
return 0;
}
4.子进程写端正常,父进程关闭读端,操作系统就会终止子进程(本质是OS通过发送信号终止掉)
四、管道通信是面向字节流的
可以简单的理解为:读取管道内容是通过单位字节一个一个读取的。
五、管道是基于文件的,而文件的生命周期是随进程的
由于管道在被进程创建打开时,OS会为管道文件创建struct file结构体,每个打开管道的进程的文件描述符表都有指向该管道内核结构体的struct file*类型指针,当打开该管道文件的进程终止或进程通过close(文件描述符)关闭了该管道文件时,管道文件的内核结构体struct file内部的count就会计数减一,当0==count时,操作系统就会自动释放管道的内核结构体。