Bash
在沒有 sleep 命令的情況下避免在 bash 中忙於等待
我知道我可以通過執行以下操作等待條件在 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