sleep 명령 없이 bash에서 바쁜 대기를 피하세요

sleep 명령 없이 bash에서 바쁜 대기를 피하세요

다음을 수행하여 bash에서 조건이 true가 될 때까지 기다릴 수 있다는 것을 알고 있습니다.

while true; do
  test_condition && break
  sleep 1
done

그러나 매 반복(수면)마다 1개의 하위 프로세스가 생성됩니다. 다음과 같이 하면 이러한 문제를 피할 수 있습니다.

while true; do
  test_condition && break
done

하지만 CPU를 많이 사용합니다(Busy Waiting). 하위 프로세스와 바쁜 대기를 피하기 위해 다음과 같은 해결책을 생각해 냈지만 보기에 좋지 않습니다.

my_tmp_dir=$(mktemp -d --tmpdir=/tmp)    # Create a unique tmp dir for the fifo.
mkfifo $my_tmp_dir/fifo                  # Create an empty fifo for sleep by read.
exec 3<> $my_tmp_dir/fifo                # Open the fifo for reading and writing.

while true; do
  test_condition && break
  read -t 1 -u 3 var                     # Same as sleep 1, but without sub-process.
done

exec 3<&-                                # Closing the fifo.
rm $my_tmp_dir/fifo; rmdir $my_tmp_dir   # Cleanup, could be done in a trap.

참고: 일반적인 경우 read -t 1 varfifo는 stdin을 소비하므로 fifo 없이는 사용할 수 없으며 stdin이 터미널이나 파이프가 아니면 작동하지 않습니다.

보다 우아한 방법으로 하위 프로세스와 바쁜 대기를 피할 수 있나요?

답변1

bash최신 버전(최소 v2)에서는 내장 기능을 런타임에 로드할 수 있습니다( enable -f filename commandname. 이러한 로드 가능한 내장 기능 중 다수는 bash 소스와 함께 배포되며 sleep그 안에 위치합니다. 물론, 가용성은 운영 체제마다(심지어 기계마다) 다를 수 있습니다. 예를 들어, openSUSE에서 이러한 내장 기능은 패키지를 통해 배포됩니다.bash-loadables.

답변2

내부 루프에 많은 하위 프로세스를 만드는 것은 나쁜 일입니다. sleep매초마다 하나의 프로세스를 생성하십시오. 괜찮아요

while ! test_condition; do
  sleep 1
done

외부 프로세스를 정말로 피하고 싶다면 FIFO를 열어둘 필요가 없습니다.

my_tmpdir=$(mktemp -d)
trap 'rm -rf "$my_tmpdir"' 0
mkfifo "$my_tmpdir/f"

while ! test_condition; do
  read -t 1 <>"$my_tmpdir/f"
done

답변3

나는 최근에 이것을 할 필요가 있었습니다. 나는 외부 프로그램을 호출하지 않고 bash를 영원히 잠들게 만드는 다음 함수를 생각해 냈습니다.

snore()
{
    local IFS
    [[ -n "${_snore_fd:-}" ]] || { exec {_snore_fd}<> <(:); } 2>/dev/null ||
    {
        # workaround for MacOS and similar systems
        local fifo
        fifo=$(mktemp -u)
        mkfifo -m 700 "$fifo"
        exec {_snore_fd}<>"$fifo"
        rm "$fifo"
    }
    read ${1:+-t "$1"} -u $_snore_fd || :
}

참고: 이전에 매번 파일 설명자를 열고 닫는 버전을 게시했지만 일부 시스템에서는 초당 수백 번 이 작업을 수행하면 결국 작동이 중단되는 것을 발견했습니다. 따라서 새로운 솔루션은 함수 호출 간에 파일 설명자를 유지합니다. Bash는 어쨌든 종료 시 이를 정리합니다.

이는 /bin/sleep과 같이 호출할 수 있으며 요청한 시간 동안 절전 모드로 전환됩니다. 인수 없이 호출되면 영원히 중단됩니다.

snore 0.1  # sleeps for 0.1 seconds
snore 10   # sleeps for 10 seconds
snore      # sleeps forever

내 블로그에 너무 많은 세부정보가 포함된 기사가 있습니다.

답변4

또는 ksh93은 내장 셸이므로 다른 옵션은 대신 이러한 셸을 사용하는 것 mksh입니다 .sleepbash

zsh또한 주어진 100분의 1초 동안 휴면하는 zselect내장 함수(loaded ) 도 있습니다 .zmodload zsh/zselectzselect -t <n>

관련 정보