进程间的通信(管道)

进程间的通信(管道)

进程间的通信(Inter-Process Communication,IPC) 是指在不同进程之间传递或交换信息。这些进程可以是运行在同一台计算机上,也可以是通过网络连接的不同计算机上的。由于不同的进程拥有不同的内存空间,因此不能通过简单地直接访问对方的内存空间来实现信息的传递或共享,需要通过一些特殊的方法来实现。

管道

  1. 匿名管道(Anonymous Pipe)
    • 匿名管道是Linux中最基本的管道类型,它没有名字,通常用于父进程和子进程之间的通信。
    • 当使用pipe()系统调用时,会创建一个匿名管道。这个系统调用返回两个文件描述符:一个用于写(通常是pipefd[1]),另一个用于读(通常是pipefd[0])。
    • 父进程和子进程分别通过这两个文件描述符进行读写操作。
    • 匿名管道是半双工的,即数据只能在一个方向上流动。
  2. 命名管道(Named Pipe 或 FIFO)
    • 命名管道也被称为FIFO(First In First Out),它有一个名字,并允许无亲缘关系的进程之间进行通信。
    • 使用mkfifo命令或mknod命令可以创建命名管道。
    • 与匿名管道不同,命名管道是持久的,即使创建它们的进程已经终止,它们仍然存在,直到被显式删除。
    • 命名管道可以是阻塞的或非阻塞的,这取决于进程如何打开它们。

匿名管道代码测试例

/*******************************************************************
*
*	file name:	fifo_text1.c
*	author	 :  m17872844806@163.com
*	date	 :  2024/06/01
*	function :  创建了一个匿名管道,测试子进程向匿名管道写入数据,父进程读取匿名管道中的数据,以实现进程间
*				的通信
* 	note	 :  None
*
*	CopyRight (c)  2023-2024   m17872844806@163.com  All Right Reseverd 
*
* *****************************************************************/
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
  
int main() {  
    int pipefd[2]; // 定义文件描述符数组,pipefd[0]用于读,pipefd[1]用于写  
  
    // 创建匿名管道  
    if (pipe(pipefd) == -1) {  
        perror("pipe");  
        exit(EXIT_FAILURE);  
    }  
  
    // 创建子进程  
    pid_t pid = fork();  
  
    if (pid == -1) {  
        // 创建子进程失败  
        perror("fork");  
        exit(EXIT_FAILURE);  
    }  
  
    if (pid == 0) {  
        // 子进程  
        close(pipefd[0]); // 关闭读端  
  
        // 向管道写入数据  
        const char *message = "Hello from child process!\n";  
        write(pipefd[1], message, strlen(message));  
  
        close(pipefd[1]); // 关闭写端  
        exit(EXIT_SUCCESS);  
    } else {  
        // 父进程  
        close(pipefd[1]); // 关闭写端  
  
        // 从管道读取数据  
        char buffer[1024];  
        ssize_t bytesRead = read(pipefd[0], buffer, sizeof(buffer) - 1);  
        if (bytesRead > 0) {  
            buffer[bytesRead] = '\0'; // 添加字符串终止符  
            printf("Received from child: %s", buffer);  
        }  
  
        close(pipefd[0]); // 关闭读端  
        wait(NULL); // 等待子进程结束  
    }  
  
    return 0;  
}

命名管道代码示例

/*******************************************************************
*
*	file name:	fifi_text2.c
*	author	 :  m17872844806@163.com
*	date	 :  2024/06/01
*	function :  将数据写入有名管道中的数据实现进程间的通信
* 	note	 :  None
*
*	CopyRight (c)  2023-2024   m17872844806@163.com  All Right Reseverd 
*
* *****************************************************************/
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <fcntl.h>  
#include <sys/stat.h>  
#include <sys/types.h>  
#include <unistd.h>  
  
#defined FIFO_PATH   "./fifo1"
int main() {  
  
    // 创建有名管道  
    if (mkfifo(fifo_path, 0666) == -1) {  
        perror("mkfifo");  
        exit(EXIT_FAILURE);  
    }  
  
    // 打开有名管道以写入数据  
    int fd = open(fifo_path, O_WRONLY);  
    if (fd == -1) {  
        perror("open");  
        exit(EXIT_FAILURE);  
    }  
  
    // 写入数据到有名管道  
    const char *message = "Hello, Named Pipe!";  
    ssize_t bytes_written = write(fd, message, strlen(message) + 1);  
    if (bytes_written == -1) {  
        perror("write");  
        exit(EXIT_FAILURE);  
    }  
  
    // 关闭管道  
    close(fd);  
  
    // 删除有名管道(可选)  
    unlink(fifo_path);  
  
    return 0;  
}
/*******************************************************************
*
*	file name:	pipe_text.c
*	author	 :  m17872844806@163.com
*	date	 :  2024/06/1
*	function :  读取有名管道中的数据实现进程间的通信
* 	note	 :  None
*
*	CopyRight (c)  2023-2024   m17872844806@163.com  All Right Reseverd 
*
* *****************************************************************/
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <fcntl.h>  
#include <unistd.h>  
  
#define MAX_BUF 256  
#defined FIFO_PATH   "./fifo1" 
int main() {  
    // 打开有名管道以读取数据  
    int fd = open(fifo_path, O_RDONLY);  
    if (fd == -1) {  
        perror("open");  
        exit(EXIT_FAILURE);  
    }  
  
    // 读取数据  
    char buffer[MAX_BUF];  
    ssize_t bytes_read = read(fd, buffer, MAX_BUF - 1);  
    if (bytes_read == -1) {  
        perror("read");  
        exit(EXIT_FAILURE);  
    }  
  
    // 确保字符串以null终止  
    buffer[bytes_read] = '\0';  
  
    // 打印读取到的数据  
    printf("Received: %s\n", buffer);  
  
    // 关闭管道  
    close(fd);  
  
    return 0;  
}

管道是Linux中一种简单而有效的进程间通信机制,它允许进程之间通过内存中的管道进行数据的读写操作,匿名管道经常用于父进程和子进程之间的通信,特别是当子进程需要执行一些操作并将结果返回给父进程时,而命名管道可以用于更复杂的场景,例如多个进程之间的数据交换或服务器与客户端之间的通信。

如果代码用法有什么问题,请将问题发至网易邮箱 m17872844806@163.com,作者将及时改正,欢迎与各位老爷交流讨论。

麻烦三连加关注!!!!

比心

posted @   琨为玉也  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示