You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux下Named Pipe工作原理及代码运行异常求助

Linux命名管道(Named Pipe)工作原理及代码问题排查

一、Linux命名管道(Named Pipe)工作原理

  • 命名管道是一种特殊文件,通过文件系统路径标识,能实现无亲缘关系进程间的通信
  • 严格遵循**FIFO(先进先出)**规则,数据写入顺序和读取顺序完全一致
  • 本质是内核中的一块缓冲区,磁盘上仅保留inode节点,不存储实际传输的数据
  • 默认阻塞特性:open()命名管道时,读端会阻塞到有写端打开,写端也会阻塞到有读端打开;可通过O_NONBLOCK标志取消阻塞
  • 传输特性:基于字节流通信,支持两端同时以读写模式打开,也可分别以只读/只写模式打开

二、代码问题分析与修复

1. 核心错误点

发送端问题

  • 运算符优先级错误:if(fd = open("./hello", O_RDWR) < 0) 中,<优先级高于=,导致fd被赋值为比较结果(0或1),而非实际文件描述符
  • 错误提示文案不符:打开失败时提示"Failed to make fifo",实际是open操作失败

接收端问题

  • mkfifo参数错误:mkfifo第二个参数是文件权限(如0666),不是打开模式(O_RDWR),会导致管道创建失败或权限异常
  • 同样存在运算符优先级错误:if(fd = mkfifo("./hello", O_RDWR) < 0) 中fd被错误赋值
  • 输出缓冲问题:printf("Waiting for fifo update"); 无换行符,导致输出被缓冲,看起来像无输出
  • 管道创建逻辑不合理:发送端先运行时会因管道不存在直接退出,接收端应负责管道创建

2. 修复后的完整代码

发送端(fifoSender.c)

#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

#define MSG_SIZE 100

// SENDER
int main() {
    char msg[MSG_SIZE] = "FIFO is for first-in, first-out.";
    int fd;

    // 修复优先级问题,修正错误提示
    if( (fd = open("./hello", O_WRONLY)) < 0 ) {
        perror("Failed to open fifo for writing");
        printf("Error code: %d\n", errno);
        exit(1);
    }
    
    int len = strlen(msg) + 1; // 包含字符串终止符

    if(write(fd, msg, len) == -1) {
        perror("Failed to write into fifo");
        exit(1);
    } else {
        printf("Succeed to write msg!\n");
    }

    close(fd); // 关闭文件描述符
    return 0;
}

接收端(fifoReader.c)

#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

#define MSG_SIZE 100

// READER
int main() {
    char msg_rc[MSG_SIZE];
    int fd;
    const char *fifo_path = "./hello";

    // 检查管道是否存在,不存在则创建
    if(access(fifo_path, F_OK) != 0) {
        // mkfifo第二个参数改为权限值,修复优先级问题
        if( mkfifo(fifo_path, 0666) < 0 ) {
            perror("Failed to create fifo");
            exit(1);
        }
    }

    // 以只读模式打开管道,修复优先级问题
    if( (fd = open(fifo_path, O_RDONLY)) < 0 ) {
        perror("Failed to open fifo for reading");
        exit(1);
    }
    
    printf("Waiting for fifo update...\n");
    ssize_t read_len = read(fd, msg_rc, MSG_SIZE);
    if(read_len == -1) {
        perror("Failed to read from fifo");
        exit(1);
    } else if(read_len == 0) {
        printf("Write end of fifo closed.\n");
    } else {
        printf("Read msg : %s\n", msg_rc);
    }

    close(fd);
    unlink(fifo_path); // 使用完删除管道
    return 0;
}

3. 运行步骤

  1. 编译代码:
    gcc fifoSender.c -o fifoSender
    gcc fifoReader.c -o fifoReader
    
  2. 先启动接收端(会阻塞等待发送端连接):
    ./fifoReader
    
  3. 在另一个终端启动发送端:
    ./fifoSender
    
  4. 接收端会输出读取到的消息,发送端输出成功提示

内容的提问来源于stack exchange,提问作者happychild

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 12:35:27