大家好,我是考100分的小小码 ,祝大家学习进步,加薪顺利呀。今天说一说进程的管道通信_进程 管道,希望您对编程的造诣更进一步.
管道
- 什么是管道?
一个进程连接到另一个进程的一个数据流称为一个“管道”。
匿名管道pipe
- 用于父子间的通信
- 管道最大64K,由环形队列组成
- 需要占用两个文件描述符,分别作为管道读端、写端
- 管道是半双工的,需要确定通信方向
父写子读,关闭父读、子写
子写父读,关闭子读、父写 - 优点:稳定、经典
pipe函数原型
头文件:<unistd.h>
int pipe(int file_descriptor[2]);
功 能:创建一无名管道
参 数:file_descriptor:文件描述符数组,其中file_descriptor[0]表示读端,file_descriptor[1]表示写端
返回值:成功返回0,失败返回-1
开辟了管道之后如何实现两个进程间的通信呢?比如可以按下面的步骤通信。
1、父进程调用pipe开辟管道,得到两个文件描述符指向管道的两端。
2、父进程调用fork创建子进程,那么子进程也有两个文件描述符指向同一管道。
3、父进程关闭管道读端,子进程关闭管道写端。父进程可以往管道里写,子进程可以从
4、管道里读,管道是用环形队列实现的,数据从写端流入从读端流出,这样就实现了进程间通信。
#include <stdlib.h>
#include <unistd.h>
#define MAXLINE 80
int main(void)
{
int n;
int fd[2];
pid_t pid;
char line[MAXLINE];
if (pipe(fd) < 0)
{
perror("pipe");
exit(1);
}
if ((pid = fork()) < 0)
{
perror("fork");
exit(1);
}
if (pid > 0) // 父进程
{
close(fd[0]);//关闭读端
write(fd[1], "hello world\n", 12);
wait(NULL);
}
else //子进程
{
close(fd[1]);//关闭写端
n = read(fd[0], line, MAXLINE);
write(STDOUT_FILENO, line, n);
}
return 0;
}
运行结果
注意事项
- 如果试图从管道写端读取数据,或者向管道读端写入数据都将导致错误发生
- 写端未写完,写端暂时无数据,读端再次去读,read发生阻塞(读太快)
- 读端未读完,写端满了,写端再次写,write发生阻塞(写太快)
- 读端关闭,写端写数据,产生SIGPIPE信号,默认会终止进程
- 写端关闭,当数据读完,再次读返回0
Linuxc/c++服务器开发高阶视频,电子书学习资料后台私信【架构】获取
有名管道fifo
pipe是有血缘关系进程之间的通信,那么当没有血缘关系的进程想要通信怎么办?
- 创建一个有名管道fifo(也叫做named pipe),解决无血缘关系的进程通信
- fifo是一个设备文件,本身无大小,在文件系统中以文件名的形式存在,因此即使进程与创建fifo的进程不存在血缘关系也依然可以通信,前提是可以访问该路径。
- fifo总是遵循先进先出的原则,即第一个进来的数据会第一个被读走
与匿名管道pipe的区别
- 提供了一个路径名与之关联,以fifo文件的形式存储于文件系统中,能够实现任何两个进程之间通信。而匿名管道对于文件系统是不可见的,它仅限于在父子进程之间的通信。 但是fifo底层是由pipe实现的。
如何创建fifo?
- 命令行上创建
- 程序内创建
头文件:
#include <sys/types.h>
#include <sys/stat.h>
函数原型:
int mkfifo(const char *pathname, mode_t mode);
做个测试,分别写两个程序,一个写,一个读
写进程
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char* argv[])
{
int fd;
char buff[1024] = "hello world\n";
if (argc < 2)
{
printf("enter you fifoname\n");
exit(1);
}
fd = open(argv[1], O_WRONLY);//只写方式打开
if (fd < 0)
{
perror("open\n");
}
write(fd, buff, strlen(buff));//写入hello world
close(fd);
return 0;
}
读进程
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char* argv[])
{
int fd;
int len;
char buff[1024] = "hello world\n";
if (argc < 2)
{
printf("enter you fifoname\n");
exit(1);
}
fd = open(argv[1], O_RDONLY);//只写方式打开
if (fd < 0)
{
perror("open\n");
}
len = read(fd, buff, sizeof(buff));
write(STDOUT_FILENO, buff, len);
close(fd);
return 0;
}
测试结果如下
首先myfifo是我们提前创建好的fifo管道文件,然后执行写进程,再执行读进程。读到了hello world,执行前后myfifo文件大小都为0
注意事项
- 当只写打开FIFO管道时,如果没有FIFO没有读端打开,则open写打开会阻塞。
- FIFO内核实现时可以支持双向通信(pipe单向通信,因为父子进程共享同一个file结构体)
- FIFO可以一个读端,多个写端;也可以一个写端,多个读端。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/11690.html