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

在C程序中使用popen()读取avrdude输出失败的问题求助

问题分析与解决办法

首先明确:你遇到的问题不是popen()使用错误,而是avrdude把设备签名这类错误/提示信息输出到了标准错误(stderr),而popen()默认只捕获标准输出(stdout)——这就是为什么你执行uname能读到内容(它输出到stdout),但avrdude的输出读不到。

下面是几种可行的解决方式:

1. 重定向stderr到stdout(最简单的办法)

修改你调用的avrdude命令,把标准错误重定向到标准输出,这样popen()就能捕获到所有输出了。命令改成:

sudo avrdude -n -q -p x192d3 -c avrisp2 2>&1

这里的2>&1就是把stderr(文件描述符2)的内容重定向到stdout(文件描述符1)。

2. 用fork/exec搭配管道替代popen()

如果不想依赖shell重定向,可以自己手动创建管道、fork子进程,然后把stderr定向到管道写端,父进程从读端读取内容。以下是一个简单的C语言示例框架:

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

int main() {
    int pipe_fd[2];
    pid_t pid;
    char buf[1024];
    ssize_t bytes_read;

    if (pipe(pipe_fd) == -1) {
        perror("pipe failed");
        exit(EXIT_FAILURE);
    }

    pid = fork();
    if (pid == -1) {
        perror("fork failed");
        exit(EXIT_FAILURE);
    }

    if (pid == 0) {
        // 子进程:关闭读端,把stderr定向到管道写端
        close(pipe_fd[0]);
        dup2(pipe_fd[1], STDERR_FILENO);
        close(pipe_fd[1]);

        // 执行avrdude命令
        execlp("sudo", "sudo", "avrdude", "-n", "-q", "-p", "x192d3", "-c", "avrisp2", NULL);
        perror("execlp failed");
        exit(EXIT_FAILURE);
    } else {
        // 父进程:关闭写端,读取管道内容
        close(pipe_fd[1]);
        while ((bytes_read = read(pipe_fd[0], buf, sizeof(buf)-1)) > 0) {
            buf[bytes_read] = '\0';
            printf("读取到内容:%s", buf);
        }
        close(pipe_fd[0]);
        wait(NULL);
    }

    return 0;
}

3. 额外注意事项

  • 如果执行sudo时需要输入密码,会导致程序卡住,建议在树莓派的sudoers文件中配置avrdude免密执行,比如添加一行:your_username ALL=(ALL) NOPASSWD: /usr/bin/avrdude(替换成你的用户名)。
  • 可以尝试给avrdude加-v参数增加输出 Verbosity,方便调试,但记得同样要处理stderr的输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 22:25:32