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

在C语言子进程中通过pipe系统调用处理cat命令输入的操作系统问题求助

解决fork/pipe配合cat命令实现输入字符串转换的问题

你的代码核心问题分析

我看了你的代码,现在有几个关键错误导致无法正常工作:

  • execvp之后的代码永远不会执行:一旦execvp("cat", ...)成功调用,子进程的整个地址空间会被cat程序替换,所以你写在execvp后面的write等代码完全不会运行,这是最致命的问题。
  • dup2的调用方向完全搞反:dup2(new_fd, old_fd)的作用是把new_fd的内容复制到old_fd,让old_fd指向new_fd的文件。比如你想让cat的输出写到管道,应该是dup2(fd2[1], STDOUT_FILENO),而不是反过来。
  • 管道关闭逻辑错误:没有及时关闭不需要的管道端,会导致进程阻塞在read/write操作上。
  • 缺少字符串转换逻辑:你还没实现把输入的dog替换成fish的核心逻辑。

修正后的代码实现

下面是调整后的代码,实现了:父进程创建管道,子进程执行cat并将输出写入管道;父进程从管道读取cat的输出,把其中的dog替换成fish,然后输出原内容+转换后的内容(符合你预期的dog fish dog fish效果):

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
#include<sys/wait.h>

// 字符串替换函数:把str中的old_str替换成new_str
void replace_string(char *str, const char *old_str, const char *new_str) {
    char buffer[1024] = {0};
    char *pos = strstr(str, old_str);
    if (!pos) return; // 没找到就直接返回

    // 复制替换前的部分
    strncpy(buffer, str, pos - str);
    // 拼接新字符串
    strcat(buffer, new_str);
    // 拼接替换后的剩余部分
    strcat(buffer, pos + strlen(old_str));
    // 把结果复制回原字符串
    strcpy(str, buffer);
}

int main(int argc , char *argv[]){
    int fd[2]; // 管道:子进程写,父进程读
    pid_t childpid;

    // 创建管道
    if (pipe(fd) == -1) {
        fprintf(stderr, "Pipe Failed\n");
        return 1;
    }

    childpid = fork();
    if (childpid < 0){
        fprintf(stderr, "Fork Failed\n");
        return 1;
    }
    else if(childpid == 0){
        // 子进程:执行cat,把输出写到管道的写端
        close(fd[0]); // 关闭不需要的读端

        // 将stdout重定向到管道写端
        dup2(fd[1], STDOUT_FILENO);
        close(fd[1]); // 重定向后可以关闭原写端

        // 执行cat命令,cat会从stdin(终端)读取输入,输出到stdout(现在是管道)
        char* myargs[] = {"cat", NULL};
        execvp(myargs[0], myargs);

        // 如果execvp失败才会走到这里
        perror("execvp failed");
        exit(1);
    }
    else {
        // 父进程:从管道读端读取cat的输出,处理后打印
        close(fd[1]); // 关闭不需要的写端

        char input_buf[1024] = {0};
        ssize_t read_len;

        // 读取管道中的内容(cat的输出)
        while ((read_len = read(fd[0], input_buf, sizeof(input_buf)-1)) > 0) {
            input_buf[read_len] = '\0'; // 确保字符串结束

            // 先输出原内容
            printf("%s", input_buf);

            // 替换所有dog为fish(如需多次替换可循环调用replace_string)
            char *temp_pos = input_buf;
            while ((temp_pos = strstr(temp_pos, "dog")) != NULL) {
                replace_string(temp_pos, "dog", "fish");
                temp_pos += strlen("fish"); // 跳过替换后的内容,避免重复替换
            }

            // 输出转换后的内容
            printf("%s", input_buf);
        }

        close(fd[0]);
        wait(NULL); // 等待子进程结束
    }

    return 0;
}

代码说明

  1. 管道使用:只需要一个管道就足够了,子进程把cat的输出定向到管道写端,父进程从管道读端读取内容。
  2. dup2的正确用法:dup2(fd[1], STDOUT_FILENO)让cat的标准输出指向管道的写端,这样cat的所有输出都会进入管道。
  3. 字符串替换:优化了替换逻辑,支持单次输入中多次出现dog的替换场景。
  4. 管道关闭:每个进程都关闭自己不需要的管道端,避免不必要的资源占用和阻塞。

测试效果

编译运行后,在终端输入dog并回车,会输出:

dog
fish

如果输入dog dog,会输出:

dog dog
fish fish

如果需要让原内容和转换内容在同一行输出,只需要调整printf的格式,比如把原内容的换行符去掉后再拼接转换内容即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 10:07:37