Linux系统编程——IPC进程间通信

目录

[一、Linux IPC 的核心种类](#一、Linux IPC 的核心种类)

1.古老的通信方式

[2.IPC 对象通信(system v 标准)](#2.IPC 对象通信(system v 标准))

[3.socket 通信](#3.socket 通信)

二、无名管道(匿名管道)

[1. 核心特性](#1. 核心特性)

2.读写行为规则

3.编程顺序

4.核心函数:pipe

5.示例代码:父子进程通过无名管道通信

三、有名管道

1.核心特性

2.编程顺序

3.核心函数:mkfifo

[4.示例代码:两个无亲缘进程通过 FIFO 通信](#4.示例代码:两个无亲缘进程通过 FIFO 通信)

四、无名管道与有名管道核心对比

五、总结


一、Linux IPC 的核心种类

1.古老的通信方式

是 Linux 早期的基础 IPC 实现,包括:

  • 无名管道
  • 有名管道
  • 信号

2.IPC 对象通信(system v 标准)

基于内核对象的通信方式,常用的有:

  • 消息队列*(使用相对较少,这里不讨论)*
  • 共享内存
  • 信号量集

3.socket 通信

支持跨主机的网络级通信,核心场景是:

  • 网络通信

注:管道的底层实现是队列**,数据遵循 "先进先出" 规则。

二、无名管道(匿名管道)

无名管道对应 pipe,是仅支持亲缘关系进程(如父子、兄弟进程)通信的方式。

1. 核心特性

  • 仅能给亲缘关系进程通信;
  • 半双工工作模式(实际编程按单工使用);
  • 是特殊文件,不支持定位操作(lseek 对管道文件描述符 / 文件指针无效);
  • 依赖文件 IO / 标准 IO 操作。

2.读写行为规则

管道的读写逻辑受缓冲区(默认 64K)和两端状态影响:

  1. 读端存在时,写端持续写超 64K 会阻塞(写得太快);
  2. 写端存在时,读端读空管道会阻塞(读得太快);
  3. 读端关闭后,写端写管道会导致写进程崩溃(管道破裂);
  4. 写端关闭后,读端读完管道内容,read 会返回 0,标志进程间通信结束。

3.编程顺序

创建管道 → fork子进程 → 读写管道 → 关闭管道

4.核心函数:pipe

cpp 复制代码
int pipe(int pipefd[2]);
  • 功能:创建并打开一个无名管道;
  • 参数:pipefd0 是无名管道的固定读端,pipefd1 是固定写端;
  • 返回值:成功返回 0,失败返回 - 1。

5.示例代码:父子进程通过无名管道通信

cpp 复制代码
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>

int main() 
{
    int pipe_fd[2];
    pid_t pid;
    char read_buf[1024] = {0};
    const char *write_data = "Hello from parent (pipe)!";

    // 1. 创建无名管道
    if (pipe(pipe_fd) == -1) 
    {
        perror("pipe create failed");
        return -1;
    }

    // 2. fork创建子进程(建立亲缘关系)
    pid = fork();
    if (pid == -1) 
    {
        perror("fork failed");
        return -1;
    }

    // 3. 父进程:关闭读端,向管道写数据
    if (pid > 0) 
    {
        close(pipe_fd[0]);  // 父进程仅写,关闭读端
        write(pipe_fd[1], write_data, strlen(write_data));
        close(pipe_fd[1]);  // 写完关闭写端
        wait(NULL);         // 等待子进程执行完毕
    }
    // 4. 子进程:关闭写端,从管道读数据
    else 
    {
        close(pipe_fd[1]);  // 子进程仅读,关闭写端
        read(pipe_fd[0], read_buf, sizeof(read_buf));
        printf("Child read: %s\n", read_buf);
        close(pipe_fd[0]);  // 读完关闭读端
    }

    return 0;
}

三、有名管道

有名管道对应 fifo,突破了亲缘关系限制,支持任意单机进程通信(只要知道管道的文件路径),且在文件系统中可见(有明确的路径名称)。

1.核心特性

  • 可给任意单机进程通信,文件系统中可见(有路径);
  • 基础特性与无名管道一致(半双工、特殊文件、不支持定位等);
  • 额外特性:若管道一端未打开,open 函数会默认阻塞。

2.编程顺序

创建有名管道 → 打开有名管道 → 读写管道 → 关闭管道 → 卸载有名管道

3.核心函数:mkfifo

cpp 复制代码
int mkfifo(const char *pathname, mode_t mode);
  • 功能:在指定路径下创建一个有权限的有名管道文件;
  • 参数:pathname 是有名管道的路径 + 名称,mode 是 8 进制的文件权限(如0666);
  • 返回值:成功返回 0,失败返回 - 1。

4.示例代码:两个无亲缘进程通过 FIFO 通信

  • 写进程(fifo_write.c):
cpp 复制代码
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>

#define FIFO_PATH "/tmp/my_fifo"

int main() 
{
    // 1. 创建FIFO文件(已存在则忽略)
    if (mkfifo(FIFO_PATH, 0666) == -1) 
    {
        perror("mkfifo failed (ignore if exist)");
    }

    // 2. 打开FIFO文件(写模式)
    int fd = open(FIFO_PATH, O_WRONLY);
    if (fd == -1) 
    {
        perror("open fifo failed");
        return -1;
    }

    // 3. 向FIFO写数据
    const char *msg = "Hello from FIFO write process!";
    write(fd, msg, strlen(msg));
    printf("Write to FIFO: %s\n", msg);

    // 4. 关闭并卸载FIFO
    close(fd);
    unlink(FIFO_PATH);
    return 0;
}
  • 读进程(fifo_read.c):
cpp 复制代码
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>

#define FIFO_PATH "/tmp/my_fifo"

int main() 
{
    char buf[1024] = {0};

    // 1. 打开FIFO文件(读模式,阻塞等待写端)
    int fd = open(FIFO_PATH, O_RDONLY);
    if (fd == -1) {
        perror("open fifo failed");
        return -1;
    }

    // 2. 从FIFO读数据
    read(fd, buf, sizeof(buf));
    printf("Read from FIFO: %s\n", buf);

    // 3. 关闭FIFO
    close(fd);
    return 0;
}

四、无名管道与有名管道核心对比

对比维度 无名管道(pipe) 有名管道(FIFO)
通信范围 仅亲缘关系进程 任意单机进程
文件系统可见性 不可见(内核维护) 可见(有路径的特殊文件)
打开特性 fork 后继承文件描述符 一端未打开时 open 默认阻塞
生命周期 随进程退出自动释放 需手动 unlink 删除
创建方式 pipe () 函数 mkfifo () 函数

五、总结

  1. 管道是 Linux 最基础的 IPC 机制,核心分为无名管道(pipe)和有名管道(FIFO)两类,均为半双工、基于队列的特殊文件;
  2. 无名管道仅支持亲缘进程通信,无需手动清理;有名管道支持任意单机进程通信,需手动创建 / 删除;
  3. 管道读写需遵循核心规则,尤其注意 "读 / 写端关闭" 后的行为,避免进程崩溃或数据异常。
相关推荐
ylscode2 小时前
OpenSSH 10.4 正式发布:后量子加密落地,多项高危漏洞得到修复
网络·安全·网络安全
DianSan_ERP3 小时前
电商架构演进:如何在高并发场景下实现多平台API的标准化履约?
运维·前端·网络·安全·架构·自动化
恒5393 小时前
Linux文件系统I
linux·运维·服务器
阿成学长_Cain3 小时前
Linux ipcs 命令超全详解:查看共享内存 / 消息队列 / 信号量,IPC 运维必备
linux·运维·服务器·网络·数据库
黯然神伤8883 小时前
AlmaLinux设置软件下载源
linux·alma
青瓦梦滋4 小时前
协议定制/序列化-反序列化(Linux视角)
linux·服务器·网络·c++
运维老郭6 小时前
【K8s运维实战】Kubernetes临时存储卷实战:emptyDir核心用法与gitRepo弃用迁移指南
运维·云原生·kubernetes
珠海西格电力6 小时前
云边端协同架构:零碳园区管理系统的技术底座
大数据·运维·人工智能·算法·架构·能源
阿成学长_Cain7 小时前
Linux dirs命令详解|Bash目录堆栈管理快速切换目录实战教程
linux·运维·前端·数据库
小羊Yveesss7 小时前
2026年微信小程序后端怎么搭建?后台、数据、接口和运维怎么选
运维·微信小程序·小程序