shell多進程


shell中沒有多進程的概念,可以通過開啟子shell並在后台執行來實現並發。

    串行執行

#!/bin/bash
start=`date +"%s"`
for (( i=0; i<10; i++ ))
do
    {
        echo "execute"
        sleep 1
    }
done

end=`date +"%s"`
echo "time: " `expr $end - $start`
12
 
1
#!/bin/bash
2
start=`date +"%s"`
3
for (( i=0; i<10; i++ ))
4
do
5
    {
6
        echo "execute"
7
        sleep 1
8
    }
9
done
10
11
end=`date +"%s"`
12
echo "time: " `expr $end - $start`

    執行時間為10秒

    

    並發執行

    讓for循環中的代碼在后台子shell中執行,只需在for循環的結尾加上&,並且在for循環外加上wait語句,等待子進程結束即可。

#!/bin/bash
start=`date +"%s"`
for (( i=0; i<10; i++ ))
do
    {
        echo "execute"
        sleep 1
    }&
done
wait
end=`date +"%s"`
echo "time: " `expr $end - $start`
12
1
#!/bin/bash
2
start=`date +"%s"`
3
for (( i=0; i<10; i++ ))
4
do
5
    {
6
        echo "execute"
7
        sleep 1
8
    }&
9
done
10
wait
11
end=`date +"%s"`
12
echo "time: " `expr $end - $start`

    執行時間為1秒,速度提升了10倍。


    這種方式比較簡單,但是有個弊端,無法控制子進程的數量,如果循環一萬次,會產生一萬個子進程,造成不可預期的情況。

    可以通過命名管道來控制子進程的數量

    管道可以用於進程間通信,一個進程向管道中寫入數據,同時另一個進程從管道中讀取數據,管道為空進程會被阻塞,只有一個進程讀或者一個進程寫管道時,進程也會被阻塞。

    通常使用的 cat | grep name 中的 | 是無名管道。

     

    利用命令管道控制並發數量的實例

#!/bin/bash

fd_fifo=/tmp/fd_1  
mkfifo $fd_fifo      #創建命令管道(pipe類型文件)
exec 6<>$fd_fifo     #將管道的fd與6號fd綁定
proc_num=5           #進程個數
count=0;
#預分配資源
for ((i=0;i<$proc_num;i++))
do
    echo >& 6        #寫入一個空行
done

start=`date +"%s"
for (( i=0; i<10; i++ ))
do
  read -u 6          #讀取一個空行
  {
      echo "execute"
      sleep 1
      echo >& 6      #完成任務,寫入一個空行
  }&                 #后台執行
done
wait                 #等待所有的任務完成
exec 6>&-           #關閉fd 6描述符,stdou和stdin
exec 6<&-           
rm -f $fifo          #刪除管道

end=`date +"%s"`
echo "time: " `expr $end - $start`
x
1
#!/bin/bash
2
3
fd_fifo=/tmp/fd_1  
4
mkfifo $fd_fifo      #創建命令管道(pipe類型文件)
5
exec 6<>$fd_fifo     #將管道的fd與6號fd綁定
6
proc_num=5           #進程個數
7
count=0;
8
#預分配資源
9
for ((i=0;i<$proc_num;i++))
10
do
11
    echo >& 6        #寫入一個空行
12
done
13
14
start=`date +"%s"
15
for (( i=0; i<10; i++ ))
16
do
17
  read -u 6          #讀取一個空行
18
  {
19
      echo "execute"
20
      sleep 1
21
      echo >& 6      #完成任務,寫入一個空行
22
  }&                 #后台執行
23
done
24
wait                 #等待所有的任務完成
25
exec 6>&-           #關閉fd 6描述符,stdou和stdin
26
exec 6<&-           
27
rm -f $fifo          #刪除管道
28
29
end=`date +"%s"`
30
echo "time: " `expr $end - $start`
執行時間為2秒(每次有5個進程在同時執行)

初始化向管道中寫入5行空字符
父shell進程執行read -u 6,會從管道中讀取一行,當管道為空時read -u會阻塞,保證最多只有5個shell進程在后台執行。
子shell進程執行echo >& 6,會向管道中寫入一行,父shell進程阻塞狀態解除,可以繼續開啟子shell執行任務。
父shell進程執行完10次循環后,調用wait函數,等待子shell執行完畢,回收資源。
如果不加上wait語句,父進程會直接退出,導致子進程成為孤兒進程(孤兒進程為被pid為1的init進程接管);或者子進程提前退出, 父進程未執行完但不知道子進程的退出狀態,會使子進程成為僵屍進程。

父進程的變量會被復制一份到子進程中,變量在子進程中的任何修改不會影響父進程中的變量。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM