博客主页:https://blog.csdn.net/2301_779549673
欢迎点赞 收藏 ⭐留言 如有错误敬请指正!
本文由 JohnKi 原创,首发于 CSDN
未来很长,值得我们全力奔赴更美好的生活✨
数据传输:一个进程需要将它的数据发送给另一个进程
资源共享:多个进程之间共享同样的资源。
通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。
什么是管道
管道是Unix中最古老的进程间通信的形式。
我们把从一个进程连接到另一个进程的一个数据流称为一个管道
#include
功能:创建一无名管道
原型
int pipe(int fd[2]);
参数
fd:文件描述符数组,其中fd[0]表示读端,fd[1]表示写端返回值:
成功返回0,失败返回错误代码
例⼦:从键盘读取数据,写⼊管道,读取管道,写到屏幕
#include
#include
#include
#include
int main(){
int fds[2];
char buf[100];
int len;
if(pipe(fds) == -1){
perror("make pipe");
exit(1);
}
// read from stdin
while(fgets(buf, 100, stdin)){
len = strlen(buf);
if(write(fds[1], buf, len) != len){
perror("write to pipe");
break;
}
memset(buf, 0x00, sizeof(buf));
// read from pipe
if((len = read(fds[0], buf, 100)) == -1){
perror("read from pipe");
break;
}
// write to stdout
if(write(1, buf, len) != len){
perror("write to stdout");
break;
}
}
}
#include
#include
#include
#include
int main() {
int fd[2];
pid_t pid;
// 创建管道
if (pipe(fd) == -1) {
perror("pipe");
return 1;
}
// 创建子进程
pid = fork();
if (pid < 0) {
perror("fork");
return 1;
}
else if (pid > 0) { // 父进程
// 父进程关闭管道读端
close(fd[0]);
// 父进程向管道写入数据
char* message = "Hello from parent!";
write(fd[1], message, sizeof(message));
// 父进程关闭管道写端
close(fd[1]);
}
else { // 子进程
// 子进程关闭管道写端
close(fd[1]);
// 子进程从管道读取数据
char buffer[100];
read(fd[0], buffer, sizeof(buffer));
printf("Child received: %s\n", buffer);
// 子进程关闭管道读端
close(fd[0]);
}
return 0;
}
总的来说可以归结为下面这张图,但是与上面代码有所不同的是,上述代码仅仅只能实现一次性的管道传输。
这部分代码实现了父子进程之间持续的双向通信,只要不手动终止程序,它们就可以一直交换消息。
#include
#include
#include
#include
#include
#define BUFFER_SIZE 100
int main() {
int parent_to_child[2];
int child_to_parent[2];
pid_t pid;
// 创建两个管道,一个用于父进程到子进程,一个用于子进程到父进程
if (pipe(parent_to_child) == -1 || pipe(child_to_parent) == -1) {
perror("pipe");
return 1;
}
pid = fork();
if (pid < 0) {
perror("fork");
return 1;
} else if (pid > 0) { // 父进程
close(parent_to_child[0]); // 关闭父进程到子进程管道的读端
close(child_to_parent[1]); // 关闭子进程到父进程管道的写端
char buffer[BUFFER_SIZE];
while (1) {
// 父进程向子进程发送消息
printf("Parent: Enter a message to send to child (or 'quit' to exit): ");
fgets(buffer, BUFFER_SIZE, stdin);
buffer[strcspn(buffer, "\n")] = 0; // 去除换行符
if (strcmp(buffer, "quit") == 0) {
break;
}
write(parent_to_child[1], buffer, strlen(buffer) + 1);
// 父进程从子进程接收消息
ssize_t n = read(child_to_parent[0], buffer, BUFFER_SIZE);
if (n > 0) {
printf("Parent received from child: %s\n", buffer);
}
}
close(parent_to_child[1]);
close(child_to_parent[0]);
} else { // 子进程
close(parent_to_child[1]); // 关闭父进程到子进程管道的写端
close(child_to_parent[0]); // 关闭子进程到父进程管道的读端
char buffer[BUFFER_SIZE];
while (1) {
// 子进程从父进程接收消息
ssize_t n = read(parent_to_child[0], buffer, BUFFER_SIZE);
if (n > 0) {
if (strcmp(buffer, "quit") == 0) {
break;
}
printf("Child received from parent: %s\n", buffer);
}
// 子进程向父进程发送消息
printf("Child: Enter a message to send to parent (or 'quit' to exit): ");
fgets(buffer, BUFFER_SIZE, stdin);
buffer[strcspn(buffer, "\n")] = 0; // 去除换行符
if (strcmp(buffer, "quit") == 0) {
break;
}
write(child_to_parent[1], buffer, strlen(buffer) + 1);
}
close(parent_to_child[0]);
close(child_to_parent[1]);
}
return 0;
}
从内核角度来看,管道本质上是一种特殊的文件系统机制,用于实现进程间通信(IPC)。以下是对管道本质的内核级理解:
综上所述,从内核角度来看,管道是通过文件系统相关的数据结构(文件结构、inode 和数据页)以及相应的操作函数来实现进程间通信的一种机制,它涉及到对数据的缓冲、同步和互斥等内核级操作。
本篇博文对 管道 做了一个较为详细的介绍,不知道对你有没有帮助呢
觉得博主写得还不错的三连支持下吧!会继续努力的~