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

Ubuntu16.04下popen调用shell脚本后fgets卡住问题求助

解决popen执行后台进程时fgets卡住的问题

问题原因分析

你的C程序卡在fgets循环里无法走到printf("over============="),核心原因是shell脚本启动的Android模拟器进程没有切断与父shell的输出关联:

  • 当你在vm_manager.sh里用emulator ... &让模拟器后台运行时,它的标准输出(stdout)和标准错误(stderr)默认还是绑定到启动它的shell进程(也就是popen创建的那个shell)。
  • popen创建的管道会一直等待shell进程的stdout关闭,而shell进程会默认等待所有子进程(包括后台的emulator)结束才会退出并关闭stdout。这就导致你的C程序会一直卡在fgets里,等待永远不会到来的EOF。

解决方案

最直接的解决方式是重定向emulator的输出,切断它与shell进程的输出关联,让shell脚本启动模拟器后立即退出,这样popen的管道就能正常关闭,程序继续执行。

方案1:将emulator输出丢弃到/dev/null

修改vm_manager.sh里的模拟器启动命令,把stdout和stderr都重定向到/dev/null:

emulator -avd $VM_NAME -kernel $KERNEL -port $VM_START_PORT -no-window -writable-system -ranchu -cores 4 -gpu mesa >/dev/null 2>&1 &
  • >/dev/null:将标准输出重定向到空设备(丢弃)
  • 2>&1:将标准错误重定向到标准输出的目标(也就是同样丢弃)
  • 这样修改后,shell启动模拟器后会立即退出,不会等待后台进程,popen的管道会收到EOF,fgets返回NULL,循环结束,程序就能打印"over============="并执行pclose。

方案2:将emulator输出保存到日志文件(如果需要保留日志)

如果你需要保留模拟器的启动日志,可以把输出重定向到指定文件,而不是丢弃:

# 先创建日志目录(可选,避免目录不存在报错)
mkdir -p /var/log/emulator_logs
# 启动模拟器并将输出写入日志文件
emulator -avd $VM_NAME -kernel $KERNEL -port $VM_START_PORT -no-window -writable-system -ranchu -cores 4 -gpu mesa >/var/log/emulator_logs/${VM_NAME}.log 2>&1 &

这样shell同样会立即退出,你的C程序可以继续执行,之后如果需要查看日志,直接读取这个日志文件即可。

额外注意点

  • 确保vm_manager.sh有可执行权限:如果之前没设置,执行chmod +x vm_manager.sh
  • 如果你的C程序需要确认模拟器是否成功启动,可以在shell脚本里添加启动后的检查逻辑(比如检查指定端口是否被占用),并将检查结果输出到stdout,这样C程序可以通过管道获取启动状态,同时不影响后台运行的模拟器。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:02:44