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]);
  • 功能:创建并打开一个无名管道;
  • 参数:pipefd[0] 是无名管道的固定读端,pipefd[1] 是固定写端;
  • 返回值:成功返回 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. 管道读写需遵循核心规则,尤其注意 "读 / 写端关闭" 后的行为,避免进程崩溃或数据异常。
相关推荐
晚风吹人醒.24 分钟前
SSH远程管理及访问控制
linux·运维·ssh·scp·xshell·访问控制·远程管理
AI大模型应用之禅1 小时前
全球股市估值与可持续农业垂直种植技术的关系
网络·ai
掘根1 小时前
【仿Muduo库项目】HTTP模块2——HttpRequest子模块,HttpResponse子模块
网络·网络协议·http
Uncertainty!!2 小时前
Linux多用户情况下个别用户输入密码后黑屏
linux·远程连接
necessary6532 小时前
使用Clion查看linux环境中的PG源码
linux·运维·服务器
江湖有缘3 小时前
Jump个人仪表盘Docker化部署教程:从0到 搭建专属导航页
运维·docker·容器
小猪佩奇TONY3 小时前
Linux 内核学习(14) --- linux x86-32 虚拟地址空间
linux·学习
Lam㊣3 小时前
Centos 7 系统docker:更换镜像源
linux·docker·centos
FL16238631293 小时前
win11+WSL+Ubuntu-xrdp+远程桌面闪退+黑屏闪退解决
linux·运维·ubuntu
石头5304 小时前
Kubernetes监控全栈解决方案:从零搭建Prometheus+Grafana监控体系
linux