在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
相关产品推荐
相关产品推荐

