shell本身是不支持多线程的,想要并发编程,可以使用多进程。
引言
shell多进程写法很方便,在执行的命令结尾加一个&
符号,便可以把当前操作放到后台进程执行,而当前进程可以继续执行其他操作。直接操作,进程数量会变得不可控,比如,对一个目录下每个文件都要执行一个操作,该操作通过&
放到后台进程执行,那么,当该目录下有10个文件时,就会启动10个进程,有100个文件时,就会启动100个进程。
而每个进程都是占用系统资源的,有些资源是有一定限制的,用ulimit
命令可以查看
1 2 3 4 5 6 7 8 9 10 11 12
| $ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited file size (blocks, -f) unlimited max locked memory (kbytes, -l) unlimited max memory size (kbytes, -m) unlimited open files (-n) 256 pipe size (512 bytes, -p) 1 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 2784 virtual memory (kbytes, -v) unlimited
|
可以看到,其中,进程的栈大小限制8192k bytes,即8M,当创建100个进程时,就会占用800M内存。而当内存不够时,系统就会报错提示,
1
| Resource temporarily unavailable
|
所以,需要对进程总数进行控制,下面说下通过管道控制的方式。
管道FIFO First In First Out
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| touch lock_f
trap "rm -f lock_f;exec 9<&-;exec 9>&-;exit 0" 2
thread_num=10
temp_pipe=$$.fifo mkfifo $temp_pipe exec 9<>$temp_pipe # 绑定 #rm -rf $temp_pipe
for (( i = 0; i < thread_num; i++ )); do echo done >&9
for (( i = 0; i < 20; i++ )); do { echo "$i wait" read -u9 echo "$i start" if [[ -f lock_f ]]; then echo >&9 exit fi sleep 2 echo "$i end" echo >&9 } & done
wait
rm lock_f
exec 9>&- # 关掉输出 exec 9<&- # 关掉输入
echo "all end"
|
- 通过trap拦截编号是2的信号,然后在里面执行一些操作
- 通过lock file将中断通知给所有进程
- mkfifo创建管道,然后与系统输入输出绑定,操作系统输入输出等同于操作管道
- 使用wait,等待所有进程执行完毕