"while" 루프 최적화

"while" 루프 최적화

버튼 하나만 누르면 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에 익숙하지 않은 분들을 위해 말씀드리자면 제가 사용하고 있던 루프에서 쉽게 소모될 정도로 매우 제한된 하드웨어 리소스(512MB 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

파이썬 솔루션

하나 있다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 ]

스크립트에 루트 비밀번호를 입력하지 마세요. 스크립트가 루트로 실행되면 sudo가 전혀 필요하지 않습니다. 스크립트가 루트로 실행되지 않는 경우 스크립트를 실행하는 사용자에게 sudo reboot비밀번호를 제공하지 않고 실행할 수 있는 권한을 부여하십시오. visudo다음 줄을 실행 하고 추가합니다.

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

sudoers 파일에서 동일한 사용자에 대한 항목에 비밀번호가 필요한 경우 해당 NOPASSWD항목은 나중에 와야 합니다.

다시 시작이 트리거되면 루프를 중단할 필요가 없으며 시스템은 어쨌든 중지됩니다.

이 셸 스크립트를 계속 사용하기로 결정했고 버전이 gpio너무 오래되어 하위 명령을 사용할 수 없는 경우 wfi매초마다 버튼 상태만 확인하는 향상된 버전이 있습니다. 핀은 초당 한 번만 읽히므로 이벤트가 선택되도록 하려면 최소한 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())은 파일 설명자가 준비될 때까지 차단될 수 있습니다.

효율성 측면에서 ()around true명령은 실제로 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

관련 정보