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

树莓派通过UDP触发subprocess控制raspistill预热拍照问题咨询

问题核心原因分析
  • 第一致命问题:UDP_listener 线程调用 t.join() 后会进入阻塞状态,直到 prime_camera 线程执行完毕才会继续处理后续UDP报文。但你调用的 raspistill -t 0 -o test.jpg -s 命令是长期驻留进程,没有触发信号的情况下永远不会退出,直接导致UDP监听线程彻底卡死,无法响应任何后续请求。
  • 第二潜在问题:你没有对raspistill的进程PID做持久化存储,直接用pkill匹配进程名的方式容错率很低,要是设备上同时跑了多个raspistill进程会出现误杀。
  • 第三可选优化点:你当前的实现里没有对isTakingImage状态做原子性修改,多线程并发操作同一个全局变量的时候可能出现状态不同步的问题。
修复方案
  1. 删掉UDP_listener里所有的.join()调用,不要阻塞监听线程:

原有代码里t.start()后立刻t.join()的逻辑会直接堵死监听链路,启动子线程后不需要等待子线程执行完毕,直接回到监听逻辑处理下一个报文即可。

  1. 全局存储prime_camera启动的raspistill进程PID,不要用pkill匹配进程名:
# 全局变量新增
raspistill_pid = None

修改prime_camera逻辑:

def prime_camera():
    global raspistill_pid
    cmd = 'raspistill -t 0 -o test.jpg -s'
    p1 = Popen(shlex.split(cmd))
    raspistill_pid = p1.pid

修改take_image逻辑:

import os
import signal
def take_image():
    global raspistill_pid
    if raspistill_pid is not None:
        try:
            os.kill(raspistill_pid, signal.SIGUSR1)
        except ProcessLookupError:
            # 进程已经退出,重置状态
            raspistill_pid = None
  1. 对全局状态isTakingImage、raspistill_pid的读写操作加锁,避免多线程并发竞争导致的状态异常:
import threading
state_lock = threading.Lock()
# 所有读写全局状态的地方都先加锁
with state_lock:
    # 修改/读取 isTakingImage、raspistill_pid 的逻辑
  1. 可选补充:如果需要在预热失败、拍照完成后通知UDP发送端,可以在子线程执行完对应逻辑后单独给源地址回ACK包,不要在监听线程里处理阻塞逻辑。

内容的提问来源于stack exchange,提问作者Too Long Din't Read

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 05:06:02