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

Linux下管道传递文件名后open函数调用失败的问题求解

问题分析与解决方法

核心问题

  1. 输入包含无效字符且未正确截断:父进程用read读取用户输入时,会把回车键对应的\n读入缓冲区,还直接将整个20字节缓冲区写入管道,导致子进程收到的字符串里既有\n,还有缓冲区未被覆盖的随机垃圾数据,open无法识别正确文件名。
  2. 未传递有效字符串长度:父进程固定写入20字节,而非实际读取到的有效字符数,子进程无法准确定位文件名的结束位置。

修复步骤

1. 父进程处理输入并写入有效数据

读取输入后,先把\n替换为字符串终止符\0,再只写入实际的文件名长度(包含\0),而非整个缓冲区:

// 父进程部分修改
read(STDIN_FILENO, buf,20);
// 定位换行符并替换为终止符
char *newline = strchr(buf, '\n');
if (newline != NULL) {
    *newline = '\0';
}
// 仅写入有效字符串(含终止符)
write(fp[1], buf, strlen(buf) + 1);

注意:需要新增<string.h>头文件,因为用到了strchr和strlen函数。

2. 子进程修正资源释放顺序

子进程里的管道关闭操作要放在exit之前,避免资源泄漏:

// 子进程部分修改
close(fp[1]);
int fd;
read(fp[0], buf,20);
if((fd = open(buf, O_RDONLY)) == -1) {
    close(fp[0]); // 先关闭管道再退出
    exit(1);
}
close(fp[0]);
exit(0);

完整修复代码

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <string.h> // 新增头文件

int main(){
    int fp[2];

    if (pipe(fp) < 0){
        printf("error creating pipe\n");
        exit(-1);
    }

    int id;
    char buf[20];

    id=fork();

    // 父进程部分
    if (id!=0){
        close(fp[0]);

        printf("program name: ");
        fflush(stdout);
        read(STDIN_FILENO,buf,20);
        
        // 处理换行符
        char *newline = strchr(buf, '\n');
        if (newline != NULL) {
            *newline = '\0';
        }
        
        // 写入有效文件名
        write(fp[1], buf, strlen(buf) + 1);

        int waitstatus, exitcode;
        wait(&waitstatus);

        if (WIFEXITED(waitstatus))
            exitcode = WEXITSTATUS(waitstatus);
        else
        {
            printf("Bad exit\n");
            return 0;
        }
        if (exitcode==1) printf("error, file doesn't exist\n");
        else printf("file does exist\n");

        close(fp[1]);
    }

    // 子进程部分
    else{
        close(fp[1]);
        int fd;
        read(fp[0],buf,20);
        
        if((fd = open(buf, O_RDONLY)) == -1) {
            close(fp[0]);
            exit(1);
        }
        
        close(fp[0]);
        exit(0);
    }
}

补充说明

如果之前替换\n为\0后仍无效,大概率是因为父进程依旧写入了整个20字节缓冲区,导致\0后面的垃圾数据干扰了open的识别。上述方案通过只传递有效字符串,从根源避免了这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:36:52