Оптимизация, 'в то время как' цикл

Как rsync, но использование zsync для получения с httpd сервера.

8
17.07.2013, 04:25
3 ответа

Анализ и современное решение

Сценарий является занятым циклом: это продолжает читать контакты GPIO много раз. Это не использует много памяти, но это заставляет ЦП напряженно трудиться.

Необходимо установить контакт GPIO в режиме прорисовки контура. gpio утилита имеет a wfi (ожидайте прерывания), команда, которую можно использовать для реакции на граничный триггер. (gpio wfi не существовал назад, когда вопрос задали.)

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

Решение Python

Существует библиотека 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 &
11
27.01.2020, 20:10
  • 1
    Для Вашего последнего примера Вы могли спать для части секунды. Что-то как 0.1 или возможно 0.2 должен смочь обнаружить очень короткие нажатия и все еще оставить много процессорного времени для других потоков. –  Bob 17.07.2013, 07:10
  • 2
    @Bob: В то время как мобильность, вероятно, не имеет значения в этом случае, sleep(1)принятие дробного числа секунд нестандартно. –   17.07.2013, 11:26

То, что Вы имеете, известно как занятый цикл. Ваш цикл не использует едва памяти, но это использует много ЦП. Это обычно смягчается путем добавления 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
3
27.01.2020, 20:10

Попробуйте следующее:

while ! gpio read 0 ; do
    sleep 1
done
echo password | sudo -S reboot
-1
27.01.2020, 20:10

Теги

Похожие вопросы