Skip to main content

同じGPIO/SPI/I2C/UARTを使う複数プログラム間で、systemdサービスを一時停止して排他アクセスを確保するためのコンテキストマネージャ

Project description

rpi-hw-lock

Raspberry Pi上で、複数のプログラムが同じGPIO/SPI/I2C/UARTを取り合う問題を解決するための、 軽量なPythonライブラリです。

背景・課題

Raspberry Pi上で常時稼働しているセンサー収集サービス(systemdサービス)がある状態で、 別の新しい実験用スクリプトが同じセンサー配線(GPIO/SPI/I2Cバス)を使いたい場合、 両方のプロセスが同時にハードウェアへアクセスすると、通信内容が破損する恐れがあります。 I2C・SPIは複数ステップからなるトランザクションであり、カーネルドライバはこれを プロセスをまたいで排他制御してはくれません。

これまでは、新しいスクリプトを動かす前に手動でsudo systemctl stopし、終わったら sudo systemctl startし忘れないようにする、という運用でカバーしていました。

解決方法

対象のsystemdサービスを一時的に完全停止させ、処理が終わったら(例外が発生しても) 自動的に元の状態へ復元する、Pythonのコンテキストマネージャを提供します。

ロックファイル等の「お互いに譲り合う」方式ではなく、対象プロセスを完全に停止させる 方式なので、既存のサービス側のコードを一切変更する必要がありません

インストール

pip install rpi-hw-lock

依存パッケージはありません(Python標準ライブラリのみで動作します)。

使い方

from rpi_hw_lock import exclusive_hardware_access

with exclusive_hardware_access(["sensor-tiered-client.service"]):
    # ここでGPIO/SPI/I2C/UARTを自由に使うコード
    ...
# withブロックを抜けた時点(例外が発生していても)、元々activeだったサービスだけが
# 自動的に再開されます

複数のサービスをまとめて一時停止することもできます。

with exclusive_hardware_access(["service-a.service", "service-b.service"]):
    ...

事前準備: sudoersの設定

systemctl stop/startには通常sudoが必要です。パスワード入力を求められないよう、 対象サービスのstop/startだけに絞ったsudoersルールを1回設定してください。

sudo visudo -f /etc/sudoers.d/rpi-hw-lock

以下のような内容を記載します(pisensor-tiered-client.serviceは環境に合わせて変更)。

pi ALL=(root) NOPASSWD: /usr/bin/systemctl stop sensor-tiered-client.service
pi ALL=(root) NOPASSWD: /usr/bin/systemctl start sensor-tiered-client.service

systemctl全体ではなく、対象サービスのstop/startだけに限定することで、 意図しない権限昇格を防いでいます。

事前確認: 権限が正しく設定されているか

実際に停止する前に、パスワード無しで実行できる権限が設定されているかを確認できます。

from rpi_hw_lock import check_permissions

check_permissions(["sensor-tiered-client.service"])  # 権限が無ければPermissionErrorを送出

API

関数 説明
exclusive_hardware_access(services, timeout=10.0, verify_stopped=True) コンテキストマネージャ本体。servicesは文字列1つ、またはリスト
check_permissions(services, timeout=5.0) sudoersの設定状況を事前確認する
is_active(service) 指定したサービスが現在activeかどうかを返す
ServiceControlError systemctlの実行に失敗した場合の例外

設計上の注意

  • 対象サービスにRestart=on-failureのような自動再起動設定があっても、systemctl stop による明示的な停止は自動再起動の対象になりません(systemdの仕様)。停止中に勝手に サービスが復活することはありません。
  • verify_stopped=True(既定)の場合、停止コマンド実行後に実際にinactiveへ変わったかを 再確認します。想定外の状態であればServiceControlErrorを送出します。
  • 元々inactiveだったサービスは、withブロックを抜けても起動されません(意図的に 止めていたサービスを誤って起動してしまう事故を防ぐため)。
  • 再起動(start)に失敗した場合、withブロック内で発生した例外を隠さないよう、 再起動失敗はログに記録するのみで、例外としては送出しません(両方を送出すると 元の例外が握りつぶされてしまうため)。

ライセンス

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rpi_hw_lock-0.1.0.tar.gz (8.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rpi_hw_lock-0.1.0-py3-none-any.whl (7.9 kB view details)

Uploaded Python 3

File details

Details for the file rpi_hw_lock-0.1.0.tar.gz.

File metadata

  • Download URL: rpi_hw_lock-0.1.0.tar.gz
  • Upload date:
  • Size: 8.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rpi_hw_lock-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0b710ec0039d473fa3e5f2a2e57f7aa928be9b7dcb22ff1aa73de770ad3a3a03
MD5 1fe92fca609bd62445fc2eb27add5e4c
BLAKE2b-256 5122bade6004e964efc62481e9de780b98e6312716f1a890d3e95e0493371207

See more details on using hashes here.

Provenance

The following attestation bundles were made for rpi_hw_lock-0.1.0.tar.gz:

Publisher: publish.yml on kazuki1729/rpi-hw-lock

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rpi_hw_lock-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: rpi_hw_lock-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 7.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rpi_hw_lock-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 339894f86a03f8a99e47aea7e398cacb3b05fd790599a43f782a11ce88693ae6
MD5 bae309ffd412ec5719a3d8fdff637c63
BLAKE2b-256 1c8305b267a30e134a6837518133ef119f854b1464b152aa32bbb2bf24730ddc

See more details on using hashes here.

Provenance

The following attestation bundles were made for rpi_hw_lock-0.1.0-py3-none-any.whl:

Publisher: publish.yml on kazuki1729/rpi-hw-lock

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page