C语言_Linux 进程间通信(IPC)机制详解

发布于:2025-05-15 ⋅ 阅读:(14) ⋅ 点赞:(0)

     在 Linux 系统中,进程间通信(Inter-Process Communication, IPC)是实现不同进程间数据交换和同步的核心机制。本文将通过完整的客户端 - 服务器代码示例,详细解析每种 IPC 机制的实现原理和使用方法。

    一、管道(Pipe)

    介绍

    管道是一种半双工的通信方式,数据只能在一个方向上流动,且只能在具有亲缘关系的进程间使用(如父子进程)。它基于内存缓冲区实现,是 Unix/Linux 系统中最基本的 IPC 机制。

    使用场景
    • 命令行中的管道操作(如ls | grep .txt
    • 父子进程间的简单数据传输
    • 数据流处理(如生产者 - 消费者模型)
    注意事项
    • 单向性:数据只能从写端流向读端,若需双向通信需创建两个管道
    • 阻塞特性:读 / 写操作可能阻塞,直到有数据可读 / 写空间可用
    • 亲缘关系:只能用于具有共同祖先的进程
    示例代码
    // pipe_example.c
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    
    #define BUFFER_SIZE 1024
    
    int main() {
        int fd[2];
        pid_t pid;
        char buffer[BUFFER_SIZE];
    
        // 创建管道
        if (pipe(fd) == -1) {
            perror("pipe creation failed");
            return 1;
        }
    
        // 创建子进程
        pid = fork();
        if (pid < 0) {
            perror("fork failed");
            return 1;
        }
    
        if (pid > 0) {  // 父进程 (服务器)
            close(fd[1]);  // 关闭写端
    
            // 从管道读取数据
            ssize_t bytes_read = read(fd[0], buffer, BUFFER_SIZE);
            if (bytes_read > 0) {
                buffer[bytes_read] = '\0';
                printf("Server received: %s\n", buffer);
            }
    
            close(fd[0]);  // 关闭读端
        } else {  // 子进程 (客户端)
            close(fd[0]);  // 关闭读端
    
            const char *message = "Hello from client!";
            write(fd[1], message, strlen(message));  // 向管道写入数据
    
            close(fd[1]);  // 关闭写端
        }
    
        return 0;
    }
    
    代码解析
    1. 管道创建pipe(fd)创建一对文件描述符,fd[0]用于读,fd[1]用于写
    2. 父子进程通信
      • 父进程关闭写端 (fd[1]),通过read()接收数据
      • 子进程关闭读端 (fd[0]),通过write()发送数据
    3. 资源管理:通信结束后需关闭所有文件描述符,管道随进程终止自动销毁

    二、命名管道(FIFO)

    介绍

    命名管道(FIFO)是一种特殊类型的文件,它突破了普通管道的亲缘关系限制,允许无关进程间通信。FIFO 基于文件系统路径名来标识,数据在内存中缓存,但通过文件系统接口访问。

    使用场景
    • 无关进程间的数据流通信
    • 客户端 - 服务器架构(如 Web 服务器与 CGI 脚本)
    • 系统日志服务接收多个进程的日志消息
    注意事项
    • 文件依赖性:需手动创建和删除 FIFO 文件
    • 同步问题:打开操作可能阻塞,直到有对应读 / 写操作
    • 权限控制:需设置合适的文件权限(如0666
    示例代码
    // fifo_server.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <unistd.h>
    
    #define FIFO_NAME "myfifo"
    #define BUFFER_SIZE 1024
    
    int main() {
        char buffer[BUFFER_SIZE];
        int fd;
    
        // 创建命名管道(若不存在)
        if (mkfifo(FIFO_NAME, 0666) == -1) {
            perror("mkfifo failed");
            if (errno != EEXIST) return 1;
        }
    
        printf("Server waiting for client...\n");
        
        // 打开管道读取数据(阻塞直到有写者)
        fd = open(FIFO_NAME, O_RDONLY);
        if (fd == -1) {
            perror("open failed");
            return 1;
        }
    
        // 读取数据
        ssize_t bytes_read = read(fd, buffer, BUFFER_SIZE);
        if (bytes_read > 0) {
            buffer[bytes_read] = '\0';
            printf("Server received: %s\n", buffer);
        }
    
        // 清理资源
        close(fd);
        unlink(FIFO_NAME);  // 删除命名管道
    
        return 0;
    }
    

    // fifo_client.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <unistd.h>
    
    #de

    网站公告

    今日签到

    点亮在社区的每一天
    去签到