通信示例
1. 父子进程之间
父子进程之间可以通过匿名管道进行通信
使用匿名管道进行通信的步骤:
(1)创建文件描述符 int fds[2];
(2)将文件描述符号(fd)变成管道 pipe
(3)使用管道
(4)关闭文件描述符(fd)
示例——使用匿名管道 父进程循环等待用户输入并写入管道 ,子进程循环读取管道内容并输出:
//使用匿名管道 父进程循环等待用户输入并写入管道 子进程循环读取管道内容并输出
int main()
{
//1. 创建文件描述符号 int fds[2]; fds[0] 读端 fds[1] 写端
int fds[2];
//2. 将文件描述符号(fd)变成管道 pipe
int ret = pipe(fds);
if(-1 == ret) printf("创建管道失败:%m\n"),exit(-1);
printf("创建管道成功!\n");
//3. 使用管道
if(fork()) // 父进程
{
char wbuff[1024] = {0};
// 根据用户输入向管道写内容
while(1)
{
scanf("%s",wbuff);
write(fds[1],wbuff,strlen(wbuff));
sleep(1);
}
}
else // 子进程
{
char rbuff[1024] = {0};
// 循环读取管道内容
while(1)
{
sleep(1);
int r = read(fds[0],rbuff,1023);
if(r > 0){
rbuff[r]=0;
printf(">> %s\n",rbuff);
}
}
}
//4. 关闭文件描述符(fd)
close(fds[0]);
close(fds[1]);
return 0;
}
运行结果:
2. 非父子进程之间
非父子进程之间需要通过实名管道进行通信
使用实名管道进行通信的步骤(非父子进程一般就是在两个文件中创建的不同进程,所以这里有两个文件):
文件A代码:
//文件A 数据写入端
int main()
{
//1.创建实名管道文件
int ret = mkfifo("test.pipe",0666);
if(-1 == ret) printf("创建管道文件失败:%m\n"),exit(-1);
printf("创建管道文件成功!\n");
//2.打开管道文件
int fd = open("test.pipe",O_WRONLY,0666);
if(-1 == fd) printf("打开管道文件失败:%m\n"),unlink("test.pipe"),exit(-1);
printf("打开管道文件成功!\n");
//3.循环向管道文件中写入数据
int n = 0;
char buff[1024] = {0};
while(1)
{
sprintf(buff,"Linux,学了忘得好快!%d",++n);
write(fd,buff,strlen(buff));
sleep(1);
}
//4.关闭管道
close(fd);
//5.删除管道文件
unlink("test.pipe");
return 0;
}
文件B代码:
//文件B 数据读取端
int main()
{
//2. 打开管道文件
int fd = open("test.pipe",O_RDONLY,0666);
if(-1 == fd) printf("文件打开失败:%m\n"),unlink("test.pipe"),exit(-1);
printf("文件打开成功!\n");
//3. 从管道文件中读取数据
int r = 0;
char buff[1024]={0};
while(1) // 循环读取
{
r = read(fd,buff,1023);
// 打印读取的数据
if(r > 0)
{
buff[r] = 0;
printf(">> %s\n",buff);
}
}
//4. 关闭管道
close(fd);
return 0;
}
验证效果
上面两个文件分别命名为pipe_a.cpp和 pipe_b.cpp,编译产生的可执行文件分别为pipe_a 和 pipe_b:
执行这两个程序需要打开两个终端,正确运行效果如下:
执行时,需要运行pipe_a,因为pipe_a会创建管道文件,然后因为默认阻塞而等待读端从管道读数据(只是创建了管道文件,但是还没有open):
如果先运行了pipe_b,会因为没有管道文件而退出程序:
如果先关闭读取端,会导致写入端进程结束,因为管道“不读无法写”:
先关闭写入端,读取端进程进入阻塞状态: