进程间通讯有四种方式:信号量、管道、消息队列、共享内存
我们以前已经介绍过了信号量,今天我们着重介绍一下管道。
管道可以分为有名管道和无名管道。
有名管道
有名管道利用管道文件实现进程间通讯,管道文件仅仅是磁盘上的一个文件标识,其真实数据存储在内存上。
1.命令:mkfifo filename
2.函数:int mkfifo();
对于管道文件的打开操作,必须是有读有写的。否则,open函数会阻塞。
对于管道文件指向的内存中的数据,一旦被读,则数据就“不存在”了 。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
#include<unistd.h>
#include<assert.h>
int main()
{
int fda=open("./FIFO",O_WRONLY);
assert(fda!=-1);
char buff[128];
int n=0;
while(1)
{
printf("Input sentence:");
scanf("%s",buff);
n=write(fda,buff,strlen(buff)+1);
if(n <= 0 || !strncmp(buff,"end",3))
{
break;
}
}
close(fda);
}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
#include<unistd.h>
#include<assert.h>
int main()
{
int fdb=open("./FIFO",O_RDONLY);
assert(fdb!=-1);
char buff[128];
while(1)
{
int n = read(fdb,buff,127);
if(n<=0)
{
break;
}
printf("%s\n",buff);
}
close(fdb);
}
执行结果:
无名管道
无名管道相对于有名管道而言,其不存在管道文件。
限制:无名管道能完成进程间通讯,必须借助于父子进程共享fork开的文件描述符。所以,无名管道只能应用于父子间进程之间的通讯。
int pipe(int fd[2]); 提示用户无名管道创建于打开函数pipe只需要接收两个元素的整型数组即可。
fd[0]——读 fd[1]——写
管道(有名&无名) 都是半双工通讯。 数据流向同时时刻是单向的
其中,父进程关闭读端,子进程关闭写端,父进程只负责写,子进程只负责读。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>
#include<assert.h>
int main()
{
int fd[2]={-1,-1};
pipe(fd);
pid_t n=fork();
if(n==0)
{
char buff[128];
int n=0;
close(fd[1]);
n=read(fd[0],buff,127);
int i=0;
printf("Output:");
printf("%s\n",buff);
close(fd[0]);
}
else
{
close(fd[0]);
write(fd[1],"Hello World",sizeof("Hello World"));
close(fd[1]);
waitpid(n,NULL,0);
}
}
执行结果: