「while」ループの最適化

「while」ループの最適化

ボタンを1つだけ押すと、Raspberry Piを再起動するミニスクリプトが作成されました。スクリプトは WiringPi (gpio コマンド) を使用してピン 0 (Raspberry Pi 標準番号付けシーケンスのピン 17) を入力に設定してから、1 になるまで (つまり、ボタンを押したり押したりしているとき) 値を読み取ります。

これは私のスクリプトです。

gpio mode 0 in

while (true)
do
        if [ `gpio read 0` -eq 1 ]
        then
                echo password | sudo -S reboot
                break
        fi
done &

スクリプトがうまく実行され、すべてがうまくいきます。

しかし、Piに慣れていない人のために、私は私が使っていたループで簡単に消費されるのに非常に限られたハードウェアリソース(512 MBのRAMを含む)が付属しています。

ここで私が達成しようとしているのは、無条件ループのようなものを提供する必要0なしに値が から に変わる時期を bash が調べる別の方法を探すことです。1これは可能ですか?あなたの考えを共有してください。

答え1

分析と最新のソリューション

スクリプトは忙しいループです。 GPIO ピンを読み続けます。多くのメモリを消費しませんが、CPUを使い続けます。

GPIOピンをエッジモードに設定する必要があります。これgpio便利wfiエッジトリガに応答するために使用できる(割り込み待機)コマンドがあります。 (gpio wfi質問をしたときは存在しませんでした。)

set -e
gpio mode 0 in
gpio wfi 0 rising
echo password | sudo -S reboot

Pythonソリューション

一つあるGPIOアクセス用のPythonライブラリ、エッジモードをサポートします。以下は、目的のタスクを実行できる完全にテストされていないPythonコードです。

#!/usr/bin/env python
import os
from RPi import GPIO
GPIO.wait_for_edge(0, GPIO.RISING)
system("sudo reboot")

追加のシェルプロンプト

(true)括弧はtrue完全に不要なサブプロセスを生成します。

`gpio read 0`二重引用符で囲む必要があります。引用符がない場合、コマンド出力はファイル名のワイルドカードパターンリストとして扱われます。二重引用符を使用すると、コマンドの出力は文字列として扱われます。コマンド置換と変数置換は常に二重引用符("$(some_command)"、)で囲まれています"$some_variable"。また、$(…)代わりに構文を使用する必要があります`…`。これはまったく同じ意味を持ちますが、コマンドが複雑な場合、バックティック構文にはいくつかの解析問題があります。したがって:if [ "$(gpio read 0)" -eq 1 ]

スクリプトにルートパスワードを入力しないでください。スクリプトがrootとして実行される場合、sudoはまったく必要ありません。スクリプトがrootとして実行されない場合は、スクリプトを実行しているユーザーにsudo rebootパスワードを指定せずに実行する権限を付与してください。visudo次の行を実行して追加します。

userwhorunsthescript ALL = (root) NOPASSWD: /sbin/reboot ""

sudoersファイルで同じユーザーのエントリにパスワードが必要な場合は、そのエントリは後で来る必要がありNOPASSWDます。

再起動がトリガされると、ループを中断する必要はなく、システムはとにかく停止します。

このシェルスクリプトを引き続き使用することにしましたが、バージョンが古すぎてサブコマンドがgpio利用できない場合は、wfi毎秒ボタンの状態のみを確認する拡張バージョンがあります。ピンは毎秒1回だけ読み取られるので、イベントが選択されるようにするには、少なくとも1秒間ボタンを押し続ける必要があることを意味します。

gpio mode 0 in
while sleep 1; do
    if [ "$(gpio read 0)" -eq 1 ]; then
        reboot
    fi
done &

答え2

あなたが持っているもの忙しいループ。ループはメモリをほとんど消費しませんが、多くのCPUを消費します。これは通常、sleepループ本体に追加することで軽減できます。

while (true)
do
        if [ `gpio read 0` -eq 1 ]
        then
                echo passowrd | sudo -S reboot
                break
        fi
        sleep 1
done &

忙しいサイクルから抜け出すことは、gpioあなたが何をするかによって異なります。一部のシステムコール(例select():)は、ファイル記述子が準備されるまでブロックできます。

効率性の観点から、()aroundtrueコマンドは実際にはtrueサブシェルで実行されます。これは必須ではなく、次の方法でよりよく表現できます。

while (( $(gpio read 0) != 1 )); do
    sleep 1
done
echo passowrd | sudo -S reboot

答え3

以下を試してください。

while ! gpio read 0 ; do
    sleep 1
done
echo password | sudo -S reboot

関連情報