
本文详解 raspberry pi 上 device or resource busy 错误的成因(如摄像头被残留进程占用)、快速诊断方法及多种可靠解决方案,包括终止占用进程、重启 camera service、重载内核模块和系统级恢复策略。
本文详解 raspberry pi 上 device or resource busy 错误的成因(如摄像头被残留进程占用)、快速诊断方法及多种可靠解决方案,包括终止占用进程、重启 camera service、重载内核模块和系统级恢复策略。
当你在 Raspberry Pi(尤其是 Pi 4)上使用 picamera2 进行视频流开发时,遇到如下典型错误:
RuntimeError: Failed to acquire camera: Device or resource busy
这表明底层摄像头设备已被其他进程或未释放的资源独占,导致新实例无法初始化。该问题并非代码逻辑错误,而是典型的资源竞争现象——尤其常见于调试过程中异常中断(如未按 Ctrl+C 退出 Flask 服务)后,Picamera2 实例未正确释放硬件句柄,造成设备持续“挂起”。
✅ 快速诊断:确认摄像头是否被占用
运行以下命令检查是否有残留进程正在使用摄像头:
# 查看所有访问 /dev/vchiq 或 /dev/video* 的进程 sudo lsof /dev/vchiq 2>/dev/null || echo "No process using vchiq" ls -l /dev/video* 2>/dev/null # 确认摄像头设备节点存在(通常为 /dev/video0)
若输出显示 picamera2、libcamera 或 python3 进程正在占用 /dev/vchiq,即为罪魁祸首。
✅ 推荐解决方案(按优先级排序)
1. 终止所有相关 Python 进程(最常用且安全)
# 杀掉所有含 picamera 或 libcamera 关键字的 Python 进程 sudo pkill -f "picamera2\|libcamera\|flask\|main.py" # 或更精准地杀掉当前用户的所有 python3 进程(谨慎使用) pkill -u $USER python3
⚠️ 注意:pkill 会终止匹配进程,请确保无其他关键脚本正在运行。
2. 重启 libcamera 服务(Pi OS 12+ 推荐)
Raspberry Pi OS(Bookworm 及更新版本)将摄像头管理交由 libcamera systemd 服务统一调度:
sudo systemctl restart libcamera-apps # 或完整重启摄像头子系统 sudo systemctl restart raspberrypi-camera
验证服务状态:
sudo systemctl status libcamera-apps
正常应显示 active (running)。
3. 重载摄像头内核模块(适用于 Kernel-level 占用)
若上述无效,可能是内核驱动未正确释放:
sudo modprobe -r bcm2835_v4l2 # 卸载 V4L2 模块 sudo modprobe bcm2835_v4l2 # 重新加载
? 提示:该操作会临时断开所有基于 V4L2 的摄像头访问(如 libcamera、cv2.VideoCapture),但不会影响系统稳定性。
4. 彻底恢复:重启 raspi-config 中的摄像头接口(终极手段)
若仍失败,检查并重置摄像头接口:
sudo raspi-config # → Interface Options → Camera → Disable → Reboot → Enable → Reboot
或手动启用(确保 /boot/config.txt 包含):
start_x=1 gpu_mem=128
然后执行:
sudo reboot
✅ 修复你的原始代码(避免再次触发)
你提供的代码存在两处关键问题,需同步修正:
- 变量名错误:with Picamera2() as kamera: 后却使用 camera.resolution —— 应统一为 kamera;
- 缺少 configure() 和 start() 调用:picamera2 不再支持直接 .capture_array() 循环,必须显式配置并启动流。
✅ 正确写法示例(兼容最新 picamera2>=0.5):
import io
from picamera2 import Picamera2
from flask import Flask, Response
app = Flask(__name__)
picam2 = None
def generate_frames():
global picam2
if picam2 is None:
picam2 = Picamera2()
config = picam2.create_video_configuration(
main={"size": (640, 480)},
controls={"FrameRate": 18}
)
picam2.configure(config)
picam2.start()
stream = io.BytesIO()
while True:
stream.seek(0)
stream.truncate()
picam2.capture_file(stream, format="jpeg")
stream.seek(0)
yield b"--frame\r\nContent-Type: image/jpeg\r\n\r\n" + stream.read() + b"\r\n"
@app.route("/v")
def videofeed():
return Response(generate_frames(), mimetype="multipart/x-mixed-replace; boundary=frame")
if __name__ == "__main__":
try:
app.run(host="0.0.0.0", port=5000, threaded=True)
finally:
if picam2 is not None:
picam2.stop()
picam2.close()
✅ 关键改进:
- 使用 create_video_configuration() 显式配置;
- 调用 start() 启动流;
- capture_file() 替代已弃用的 capture_array()(后者在新版本中行为变更);
- 添加 finally 块确保资源释放,杜绝下次“busy”风险。
? 总结
Device or resource busy 是 Raspberry Pi 摄像头开发中最易复现也最易解决的问题。核心原则是:每次异常退出后,务必清理残留进程或重启相关服务。养成“启动前查占用、退出后做清理”的习惯,并采用健壮的资源管理代码结构,即可彻底规避该错误。对于生产部署,建议将摄像头服务封装为 systemd unit,并设置 Restart=on-failure,实现自动恢复。











