while 循环运行 dd 命令时 CPU 使用率高

jam*_*fer 5 command-line scripts dd

我使用此命令从命名管道读取连续数据:

{ while :; do dd iflag=fullblock iflag=nonblock bs=65536 count=1 2> /dev/null | redis-cli -x PUBLISH myChannel ; done } < myFifo
Run Code Online (Sandbox Code Playgroud)

问题是,即使我同时运行 50 个命令,CPU 使用率也会很高。该过程应该是长时间运行的,并且其中许多过程应该同时工作。

那么,其原因是什么以及如何预防呢?谢谢。

Raf*_*ffa 7

如果我没记错的话,您正在使用dd缓冲目的...在您的情况下可能不需要循环...dd如果您不设置,将继续读取并提供指定大小的数据块count这指示dd在完成指定的读/写次数后退出)或iflag=nonblockYou\xe2\x80\x99d 希望阻塞 I/O成功启动读取并继续从命名管道读取dd)并像这样使用它:

\n
dd if=myFifo iflag=fullblock bs=65536 2> /dev/null | redis-cli -x PUBLISH myChannel\n
Run Code Online (Sandbox Code Playgroud)\n

在这种情况下,它应该仅在到达输入文件末尾时退出(例如,当命名管道的编写器终止/关闭管道时)。

\n

或者要保持管道始终打开等待写入,请像这样使用它:

\n
tail -c +1 -F myFifo | dd iflag=fullblock bs=65536 2> /dev/null | redis-cli -x PUBLISH myChannel\n
Run Code Online (Sandbox Code Playgroud)\n

或者,如果您的应用程序期望流/管道结束(例如EOFclose_write...顺便说一句,这不是流应用程序的最佳选择),请使用GNU 并行,如下所示:

\n
tail -c +1 -F myFifo | parallel --max-procs 1 -P 1 -j 1 --pipe --block 64k -k \'redis-cli -x PUBLISH myChannel\'\n
Run Code Online (Sandbox Code Playgroud)\n

这应该类似于您的循环,但仅在您需要它的地方 \xe2\x80\xa6 它将以一种相当受控和资源感知的方式执行 \xe2\x80\xa6 它也应该保持命名管道即使在写入之间也保持打开状态,保留每一位流并缩短管道。

\n


ter*_*don 2

while :正在向您的 CPU 发送垃圾邮件。任何循环中的命令while :;都会导致 CPU 使用率过高。例如:

while :; do echo foo > /dev/null; done
Run Code Online (Sandbox Code Playgroud)

或者,更明显的是,无操作:

while :; do true; done
Run Code Online (Sandbox Code Playgroud)

您运行的命令几乎无关紧要:如果命令本身不需要太多时间,那么就会while导致 CPU 使用率很高。这while :意味着一旦命令结束,循环就会重新启动,一遍又一遍。由于这dd几乎会立即完成,这意味着它会一遍又一遍地启动,每秒多次,因此会占用 CPU 负载。

解决方案是在调用之间添加一个小暂停:

{ 
  while :; do 
    dd iflag=fullblock iflag=nonblock bs=65536 count=1 2> /dev/null | 
      redis-cli -x PUBLISH myChannel 
    sleep 0.1
  done 
} < myFifo
Run Code Online (Sandbox Code Playgroud)

即使在运行之间添加 0.1 秒的睡眠也会阻止 CPU 过度消耗。