我们知道进程间通信方式有:管道,FIFO,消息队列,共享存储,信号量,套接字,STREAMS这几种,今天我们来谈一谈pipe和FIFO。
首先我们先来看一下定义:
管道pipe:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
命名管道FIFO:有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
我们先来看一下管道:
一般管道有这样的应用场景,父进程给一个只写信号到管道,子进程进行读取,或者子写父读。在管道等待输入的过程我们称为阻塞,要等待子(父)进程完成写入后,才打开。
示例代码如下:
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
int main()
{
int fd[2];
int pid;
char buf[128];
if(pipe(fd)==-1){
printf("create error!\n");
}
pid=fork();
if(pid<0){
printf("create child error!\n");
}
else if(pid>0){
sleep(2);
printf("this is father\n");
close(fd[0]);
write(fd[1],"write from father",strlen("write from father"));
wait();
}
else{
printf("this is child\n");
close(fd[1]);
read(fd[0],buf,128);
printf("read from father: %s\n",buf);
exit(0);
}
return 0;
}
简单讲一下代码 :创建管道成功后,父进程创建子进程并且在两秒后开始写入数据进入管道,这时候子进程一直处于阻塞状态,直到有数据进入管道,read才得到执行。
看一下运行结果:
两秒后
接下来我们讲一下FIFO的应用场景:
当前进程作为只读端创建完FIFO后一直处于阻塞状态,直到作为只写端的进程写入数据进管道后,打开阻塞状态。
我们来看一下代码:
只读端:
#include<stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<errno.h>
#include<fcntl.h>
int main()
{
char buf[30]={0};
int nread=0;
int a;
int cnt=0;
a=mkfifo("./f1",0600);
if((a ==-1) && errno!=EEXIST){
printf("mkfifo error!\n");
perror("why:");
}
int fd=open("f1",O_RDONLY);
printf("open success\n");
while(cnt<5){
nread=read(fd,buf,30);
printf("read %d byte from fifo,context:%s\n",nread,buf);
cnt++;
}
close(fd);
return 0;
}
只写端:
#include<stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<string.h>
int main()
{
int cnt=0;
char *str="message from fifo";
int fd=open("f1",O_WRONLY);
printf("write open success\n");
while(1){
write(fd,str,strlen(str));
sleep(1);
if(cnt ==5){
break;
}
}
close(fd);
return 0;
}
运行结果:
在执行只读程序后,进入阻塞,接下来我们执行write程序
可以看到阻塞状态被打开,并打印了5次收到的消息。
以上就是关于Linux进程间通信–管道(pipe)与命名管道(FIFO)以及其阻塞状态的浅谈,尚有不足之处,请各位大神指正。
salute CLC