一、基本概念
进程间通信意味着两个不同进程之间可以交换数据,为了完成这一点,操作系统中提供两个进程可以同时访问的内存空间。
进程不同于线程,不同线程使用同一片内存空间,但是不同进程具有不同的完全独立的内存空间。因此,要实现进程间通信就得考虑其他特殊方法。
二、通过管道实现进程间通信
管道是不属于进程的资源,而是和套接字一样,属于操作系统的资源。所以两个不同进程可以通过管道进行通信。
#include <unistd.h>
int pipe(int filedes[2]);
/*
成功返回 0 , 失败返回 -1.
filedes[0] : 通过管道接收数据时使用的文件描述符, 即管道出口
filedes[1] : 通过管道传输数据时使用的文件描述符, 即管道入口
*/
管道的简易创建和使用。
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define BUF_SIZE 40
int main()
{
char *buf = "who are you";
char buff[BUF_SIZE];
//定义管道出入口
int guandao[2];
//初始化管道
pipe(guandao);
//创建进程实现通信
pid_t pid = fork();
if(pid == 0)//子进程
{
write(guandao[1], buf, strlen(buf));
}
else{
read(guandao[0], buff, sizeof(buff));
puts(buff);
}
return 0;
}
运行如下:
三、进程间双向通信
注意,以上创建的父子进程虽然同时拥有管道出口和管道入口。但是数据进入管道之后就会成为无主数据,此时先读取管道数据的进程会获取无主的数据,其他进程后面再读取时将没有数据,所有,我们可以通过设置先后读取顺序(即延时读取)来实现双向通信。
1、延时读取实现双向通信
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define BUF_SIZE 100
int main()
{
char *buf = "who are you";
char *buf1 = "I am your parent";
char buff[BUF_SIZE];
//定义管道出入口
int guandao[2];
//初始化管道
pipe(guandao);
//创建进程实现通信
pid_t pid = fork();
if(pid == 0)//子进程
{
write(guandao[1], buf, strlen(buf));
close(guandao[1]);//使用之后及时关闭管道,能保证安全
sleep(1);//延时1秒。等待数据被父进程先读取,再去读取父进程写入的数据
read(guandao[0], buff, BUF_SIZE);
printf("recv_from_parent: %s\n", buff);
close(guandao[0]);
}
else{
//父进程向读后写,读取之后管道已没有数据,不需要延时等待
read(guandao[0], buff, BUF_SIZE);
close(guandao[0]);
printf("recv_from_son: %s\n", buff);
write(guandao[1], buf1, strlen(buf1));
close(guandao[1]);
sleep(2);
}
return 0;
}
程序执行情况如下:
2、创建两个管道分别读取和写入
上面延时可以实现双向通信,但是在使用过程中太过繁杂,且数据过大时,不方便计算延时使数据完全写入。所以推荐使用下面的创建两个管道的通信方式。
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define BUF_SIZE 40
int main()
{
char *buf = "who are you";
char buff[BUF_SIZE];
//定义管道出入口
int guandao[2];
int guandao1[2];
//初始化管道
pipe(guandao);
pipe(guandao1);
//创建进程实现通信
pid_t pid = fork();
if(pid == 0)//子进程
{
write(guandao[1], buf, strlen(buf));
close(guandao[1]);//使用之后及时关闭管道,能保证安全
read(guandao1[0], buff, sizeof(buff));
printf("recv_from_parent: %s\n", buff);
close(guandao1[0]);
}
else{
read(guandao[0], buff, sizeof(buff));
close(guandao[0]);
printf("recv_from_son: %s\n", buff);
write(guandao1[1], "i am your parent", sizeof("i am your parent"));
close(guandao1[1]);
}
return 0;
}
运行结果: