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

