【问题标题】:How to prevent concurrent access to a resource such as a USB device?如何防止对 USB 设备等资源的并发访问?
【发布时间】:2013-08-06 19:40:20
【问题描述】:

我希望能够在多个应用程序中使用 USB 设备(例如,我运行一个 Flask Web 应用程序),确保一次只有一个使用它。

就我而言,我使用继电器来打开/关闭一扇门。门大约需要 20 秒才能打开。在此期间不应激活继电器,因为这会将门锁在中间。

提前致谢!

【问题讨论】:

  • 你考虑过使用锁文件吗?
  • 这样会很简单,但必须小心使用“安全技巧”,例如计时器,以避免资源因错误而被永久锁定。
  • 是的,任何文件锁定机制都是如此。您可以在锁文件中写入进程的 PID,并在您尝试获取锁时检查它是否仍在运行,并在必要时实现额外的超时机制。

标签: python concurrency locking semaphore superglobals


【解决方案1】:

不完全是您问题的答案,但也许是关于如何在不使用全局变量的情况下解决这个问题的另一个想法。

您为什么不编写一个小程序来控制您的 USB 设备。此脚本在您的服务器上运行一次(一个实例),并负责以您需要的方式与设备进行通信。它还负责并发处理。

现在通过管道、套接字等使用此脚本从您的 Web 应用程序进行通信,向它发送命令并从中接收结果。

【讨论】:

  • “管道”(我想就像在 UNIX shell 管道中一样,由pipes 模块定义?)应该如何处理单独启动的进程之间的通信?例如,我将使用启动脚本 (init.d) 启动 USB 控制程序,而我的 Web 应用程序使用 mod_wsgi 运行。
  • 有各种各样的选择。在 Google 上寻找 python 代理,你会看到一些。第一个结果是rabbitmq,它是一个流行的与Python 配合使用的。
  • 谢谢!我选择了另一个答案作为接受的答案,但这没有任何意义。你的不一样,你的想法也很好。我什至可能更喜欢它,因为我可能会得到其他要求。
【解决方案2】:

您有许多可能的解决方案。

posix_ipcsysv_ipc Python 模块提供了一个命名信号量类。您可以将信号量初始化为 1,并让所有 Web 进程在向 USB 设备发送命令时获取信号量。

使用文件锁可以实现有点类似的机制,可能使用fcntl.lockf

另一种完全不同的方法是在您的 Web 服务器进程和 USB API 之间放置一个新进程。该进程公开了一个 API,该 API 接收来自 Web 服务器工作人员的请求,并通过作为单线程进程的方式将这些请求隐式序列化到 USB 设备中。

【讨论】:

  • 我试过 posix_ipc。我同时运行了该程序的两个实例,它让我在两个实例中都获得了信号量。这正常吗?在那种情况下 posix_ipc 或 sysv_ipc 不能解决我的问题。 pastebin.com/RWHptWyd
  • 我很容易得到fcntl.lockf 的工作。应该小心,但不要让它在出现错误时永久锁定(这适用于大多数解决方案)。
  • 当您创建信号量计数时,您没有将其初始化为 1,第三个参数设置为 1)。奇怪的是,您的测试可以获取信号量,在我看来,您粘贴的代码没有一个实例应该通过,因为信号量开始锁定。请注意,aquire 减少计数,release 增加计数。
  • 他们实际上都通过了。我不熟悉信号量。我想如果 initial_value 为 0,它将开始“锁定”并且所有 acquires 都会失败。我应该使用初始值 1。这是你的意思吗?我还尝试了两次连续调用acquire(initial_value=1),它们都成功了。出了点问题,不是吗?
  • 我的测试似乎运行良好,我一次只能运行其中一个:pastebin.com/2d1v5Kth
【解决方案3】:

您可以在配置中添加一个变量(确保其大写)

app.config['YOUR_GLOBAL'] = 'your global'

http://flask.pocoo.org/docs/config/

【讨论】:

  • 对不起,我刚试了,这不起作用。我的测试是这样的:如果它不存在,则将全局设置为 False,否则获取值。全局在每个新会话中都不存在,所以它不是像我问的那样被所有会话共享。
猜你喜欢
  • 2012-07-30
  • 2022-07-21
  • 1970-01-01
  • 1970-01-01
  • 2016-08-02
  • 2016-09-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-04
相关资源
最近更新 更多