进程间通信是指在不同进程之间传播或交换信息。
IPC的方式有:管道(有名管道、无名管道)、信号量、共享内存、消息队列、套接字。
管道
通常指无名管道是NUIX系统IPC最古老的形式。和普通文件最大的区别:写入的文件在内存中
特点:1、半双工(同一时刻数据只能在一个方向上流动),具有固定的读端和写端。
2、写管道的数据在内存中。
3、有有名管道和无名管道区别,有名管道在任意两个进程之间通信,无名管道只能在父子进程之间通信。
无名管道是通过pipe函数创建的
#include <unistd.h>
int pipe(int fd[2]);
返回值:成功0,失败-1
当一个管道建立时,它会创建两个文件描述符:fd[0]为读而打开,fd[1]为写而打开
如果要求数据从父进程流向子进程,则关闭父进程读端,关闭子进程写端。如下图
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<assert.h>
#include<fcntl.h>
#include<sys/types.h>
int main()
{
int fd[2];
assert(pipe(fd)!=-1);
pid_t pid = fork();
assert(pid!=-1);
if(pid == 0)
{
close(fd[1]);//子进程读,关闭写fd[1]
while(1)
{
char buff[128]={0};
if(read(fd[0],buff,127)==0)// 将fd[0]所指的文件,读127个字节,放入buff中,然后输出
{
break;
}
printf("child read:%s\n",buff);
}
close (fd[0]);
exit(0);
}
else
{
close(fd[0]);//父进程写 关闭读fd[0]
while(1)c
{
char buff[128]={0};
fgets(buff,128,stdin);//从输入流中读取128个字节到buff
if(strncmp(buff,"end",3)==0)
{
break;
}
write(fd[1],buff,strlen(buff));//buff所指的文件写strlen(buff)个字节到fd[1]所指的文件中
}
close(fd[1]);
exit(0);
}
}
FIFO有名管道也称命名管道,是一种文件类型
FIFO的通信方式类似于在进程中使用文件来传输数据,只不过FIFO类型文件同时具有管道的特性。在数据读出时,FIFO管道中同时清除数据,并且“先进先出”。要同时打开一读一写
管道为空,写端没有关闭,read阻塞
写端关闭,读端的read返回0
1、两者区别
有名管道可以在任意两个进程之间通信。mkfifo
无名管道只能在父子进程之间通信。Pipe()
2、写入管道的数据在内存中存放(有名管道 无名管道) 磁盘上存放的是属性信息,属性和数据是分开存储
3、通讯方式:半双工(单工 半双工对讲机 全双工)
4、程序有关:管道为空,写不会阻塞,读操作会阻塞(可以设置非阻塞,这时直接返回错误-1)管道满,写阻塞,读操作不会阻塞。空间还有多少写多少。
操作管道,读端和写端都必须存在。
如果写端关闭,读返回0(意思是读到0个字节),也不会阻塞
如果读端关闭,写会产生异常SIGPIPE 程序退出
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<fcntl.h>
int main()
{
int fd= open("fifo",O_WRONLY);//只写 fd为文件描述符,以写的方式打开fifo
assert(fd !=-1);
printf("fd=%d\n",fd);
while(1)
{
char buff[128]={0};
printf("input\n");
fgets(buff,128,stdin);
if(strncmp(buff,"end",3)==0)
{
break;
}
write(fd,buff,strlen(buff));
}
close(fd);
exit(0);
}
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<fcntl.h>
int main()
{
int fd = open("fifo",O_RDONLY);//只读
assert(fd !=-1);
printf("fd=%d\n",fd);
while(1)
{
char buff[128]={0};
int n = read(fd,buff,127);
if(n==0)
{
break;
}
printf("n=%d\n buff=%s\n",n,buff);
}
close(fd);
exit(0);
}
管道是怎么实现的
实现: