基于管道的进程间通信模型
为了完成进程间通信,需要先建立管道。管道不属于进程的资源而是和套接字一样属于操作系统。两个进程通过操作系统提供的内存空间进行通信。
创建管道的API:
#include <unistd.h>
//成功返回 0,失败返回 -1
int pipe(int filedes[2]);
接口参数为文件描述符组成的数组。filedes[0]管道出口,filedes[1]管道入口。
进程间通关管道简单通信示例:
#include <unistd.h>
#include <stdio.h>
int main()
{
int fds[2];
char str[] = "How are you!";
char buff[128] = {0};
pid_t pid;
//创建通信管道
if(pipe(fds) == -1)
{
printf("Error pipe!\n");
return 0;
}
pid = fork();
if(pid == 0)
{
//子进程向管道写数据
write(fds[1], str, sizeof(str));
}
else
{
//父进程从管道读数据
read(fds[0], buff, 128);
puts(buff);
}
return 0;
}
子进程拿到fds[1]向里面写数据,父进程拿到fds[0]从里面读数据,模型就像下图这样:
需要注意的是管道中的数据是无主的。也就说任何进程拿到了fds[0]都可以从里面读数据;任何进程拿到了fds[1],都可以向里面写数据。模型如下图:
这个模型下是保证不了消息的属主的,子进程可能读到的是自己放入管道的消息,也可能是父进程放入管道的消息;父进程亦然。
如果要保证全双工通信,则必须用两个管道,模型如下:
#include <stdio.h>
#include <unistd.h>
int main()
{
int fds1[2];
int fds2[2];
char pstr[] = "Parant process sends message!\n";
char cstr[] = "Child process sends message!\n";
char buff[32] = {0};
if(pipe(fds1) == 0 && pipe(fds1) == 0)
{
}
else
{
printf("Error pipe(fds)!\n");
return 0;
}
pid_t pid;
pid = fork();
if(pid == 0)//子进程 用 fds[1]写,用fds1[0]读。父进程用fds1[1]写,用fds2[0]读。
{
write(fds1[1], cstr, sizeof(cstr));
//sleep(1);
read(fds2[0], buff, sizeof(buff));
puts(buff);
}
else
{
read(fds1[0], buff, sizeof(buff));
puts(buff);
write(fds2[1], pstr, sizeof(cstr));
sleep(3);
}
return 0;
}