Сценарий является занятым циклом: это продолжает читать контакты GPIO много раз. Это не использует много памяти, но это заставляет ЦП напряженно трудиться.
Необходимо установить контакт GPIO в режиме прорисовки контура. gpio
утилита имеет a wfi
(ожидайте прерывания), команда, которую можно использовать для реакции на граничный триггер. (gpio wfi
не существовал назад, когда вопрос задали.)
set -e
gpio mode 0 in
gpio wfi 0 rising
echo password | sudo -S reboot
Существует библиотека Python для доступа GPIO, который поддерживает режим прорисовки контура. Вот некоторый полностью непротестированный код 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 вообще. Если сценарий не работает как корень, то дайте пользователю, запускающему скрипт разрешение работать sudo reboot
не предоставляя пароль. Выполненный visudo
и добавьте следующую строку:
userwhorunsthescript ALL = (root) NOPASSWD: /sbin/reboot ""
Обратите внимание что, если существует запись для того же пользователя в sudoers файле, который требует пароля, NOPASSWD
запись должна произойти после.
После того как Вы инициировали перезагрузку, Вы не должны повреждать цикл, система остановится так или иначе.
Если Вы решаете продолжать использовать этот сценарий оболочки и Вашу версию gpio
слишком старо, чтобы иметь wfi
подкоманда, вот улучшенная версия, которая только проверяет состояние кнопки каждую секунду. Обратите внимание, что, так как контакт только читается однажды в секунду, это означает, что необходимо удержать кнопку в нажатом состоянии в течение по крайней мере одной секунды, чтобы быть уверенными, что событие взято.
gpio mode 0 in
while sleep 1; do
if [ "$(gpio read 0)" -eq 1 ]; then
reboot
fi
done &
То, что Вы имеете, известно как занятый цикл. Ваш цикл не использует едва памяти, но это использует много ЦП. Это обычно смягчается путем добавления sleep
к телу цикла.
while (true)
do
if [ `gpio read 0` -eq 1 ]
then
echo passowrd | sudo -S reboot
break
fi
sleep 1
done &
Избавление от занятого цикла будет зависеть от какой gpio
делает. Существуют системные вызовы такой как select()
, который может заблокироваться, пока дескриптор файла не готов.
До эффективности, ()
вокруг true
команда на самом деле выполняется true
в подоболочке. Это не нужно, и может быть лучше выражено следующим:
while (( $(gpio read 0) != 1 )); do
sleep 1
done
echo passowrd | sudo -S reboot
Попробуйте следующее:
while ! gpio read 0 ; do
sleep 1
done
echo password | sudo -S reboot
0.1
или возможно0.2
должен смочь обнаружить очень короткие нажатия и все еще оставить много процессорного времени для других потоков. – Bob 17.07.2013, 07:10sleep(1)
принятие дробного числа секунд нестандартно. – 17.07.2013, 11:26