shell 脚本并发调度控制
shell 脚本并发调度控制
在 shell 脚本里有时需要同时启动多个命令实现并发,对于少量程序可以采用将命令放到后台方法实现并发,并使用wait命令等待命令执行完毕。
for beam in $Allbeam
do
{
<app> <parameter>
}&
done
wait
但是当需要执行程序数量较多,并且每个程序对硬件资源需求比较大时,此时需要在脚本内实现对同时执行的程序数量进行控制,即进程调度功能。
实现进程调度最简单的方式是使用管道方法。在linux环境里管道有一个特点,如果管道中没有数据,那么取管道数据的操作就会滞留,直到管道内进入数据,然后读出后才会终止这一操作;同理,写入管道的操作如果没有读取管道的操作,这一动作就会滞留。
使用管道实现并发的一个简单的示例代码如下:
ncpu=10
tmpfile="$$.fifo" # 临时生成管道文件
mkfifo $tmpfile
exec 6<>$tmpfile
rm $tmpfile
for((i=1; i<=$ncpu; i++))
do
echo $i>&6 # 每次向管道内输出一个字符,也就是一个令牌
done
task=400
for((i=1; i<=$task; i++))
do
read -u6 cpu
{
echo "run task " $task "with cpu " $cpu
echo $cpu>&6 # 将令牌返回管道中
}
done
在上述代码中包含三部分。
- 首先使用
mkfifo
构造了一个管道文件,并将此管道绑定到标准输出设备6上。此时就可以把实际文件删除,但是标准输出仍然是可用的。 - 随后,向管道内输入特定数量的字符,具体数量与并发的进程数相等。
- 在实际运行过程中,在并发循环外首先从设备6中读取管道内字符,当字符(令牌)存在时开始执行花括号内的并发指令,并且在执行完毕后会将字符(令牌)重新输入到管道中。
使用管道形式,就实现了并发进程数量始终与管道内输入字符数相同的功能,即在shell脚本内实现进程调度功能。