oynix

于无声处听惊雷,于无色处见繁花

shell多进程并发

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,等待所有进程执行完毕
------------- (完) -------------
  • 本文作者: oynix
  • 本文链接: https://oynix.com/2022/05/b5dfca80ccdc/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

欢迎关注我的其它发布渠道