Bash

在沒有 sleep 命令的情況下避免在 bash 中忙於等待

  • March 3, 2021

我知道我可以通過執行以下操作等待條件在 bash 中變為真:

while true; do
 test_condition && break
 sleep 1
done

但它在每次迭代(睡眠)時創建 1 個子程序。我可以通過這樣做來避免它們:

while true; do
 test_condition && break
done

但它使用大量 CPU(忙於等待)。為了避免子流程和忙於等待,我想出了下面的解決方案,但我覺得它很難看:

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 var沒有 fifo 的情況下簡單地使用,因為它會消耗標準輸入,並且如果標準輸入不是終端或管道,它將無法工作。

我可以以更優雅的方式避免子流程和忙於等待嗎?

bash在(至少 v2)的較新版本中,可以enable -f filename commandname在執行時(通過)載入內置函式。許多此類可載入的內置函式也與 bash 源一起分發,並且sleep是其中之一。當然,可用性可能因作業系統(甚至機器與機器)而異。例如,在 openSUSE 上,這些內置函式通過 package 分發bash-loadables

在內部循環中創建大量子流程是一件壞事。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

引用自:https://unix.stackexchange.com/questions/68236