優化 while
循環
我創建了一個迷你腳本,只需按一下按鈕即可重新啟動我的 Raspberry Pi。該腳本簡單地使用wiringPi(gpio 命令)將pin 0(Raspberry Pi 標準編號順序中的pin 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 記憶體),可以很容易地被我正在使用的循環所消耗。
我在這裡想要實現的是為 bash 找到另一種方法來找出值何時從
0
變為 ,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密碼放在腳本中。如果腳本以 root 身份執行,則根本不需要 sudo。如果腳本未以 root 身份執行,則授予執行腳本的使用者
sudo reboot
無需提供密碼即可執行的權限。執行visudo
並添加以下行:userwhorunsthescript ALL = (root) NOPASSWD: /sbin/reboot ""
請注意,如果 sudoers 文件中有相同使用者的條目需要密碼,則該
NOPASSWD
條目必須緊隨其後。一旦觸發重新啟動,您無需中斷循環,系統無論如何都會停止。
如果您決定繼續使用這個 shell 腳本,並且您的版本
gpio
太舊而無法使用wfi
子命令,那麼這裡有一個改進的版本,它每秒只檢查按鈕狀態。請注意,由於 pin 每秒僅讀取一次,這意味著您需要按住按鈕至少一秒鐘以確保事件被拾取。gpio mode 0 in while sleep 1; do if [ "$(gpio read 0)" -eq 1 ]; then reboot fi done &