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. 管道读写需遵循核心规则,尤其注意 "读 / 写端关闭" 后的行为,避免进程崩溃或数据异常。
相关推荐
大树8814 小时前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠14 小时前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质14 小时前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
bush415 小时前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行52015 小时前
Linux 11 动态监控指令top
linux
Inhand陈工16 小时前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
网络研究院16 小时前
2026年网络安全
网络·安全·法律·法规·趋势·发展
酣大智16 小时前
ARP代理--工作原理
运维·网络·arp·arp代理
treesforest16 小时前
AI安全系统如何识别异常访问?IP风险识别正在成为关键能力
网络·人工智能·tcp/ip·安全·web安全
不会C语言的男孩16 小时前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言