shell多進程

shell中沒有多進程的概念,能夠經過開啓子shell並在後臺執行來實現併發。
shell

    串行執行api

#!/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秒
bash

    

    併發執行
併發

    讓for循環中的代碼在後臺子shell中執行,只需在for循環的結尾加上&,而且在for循環外加上wait語句,等待子進程結束便可。app

#!/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倍。
ide


    這種方式比較簡單,可是有個弊端,沒法控制子進程的數量,若是循環一萬次,會產生一萬個子進程,形成不可預期的狀況。
函數

    能夠經過命名管道來控制子進程的數量
ui

    管道能夠用於進程間通訊,一個進程向管道中寫入數據,同時另外一個進程從管道中讀取數據,管道爲空進程會被阻塞,只有一個進程讀或者一個進程寫管道時,進程也會被阻塞。spa

    一般使用的 cat | grep name 中的 | 是無名管道。
code

     

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

#!/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進程接管);或者子進程提早退出, 父進程未執行完但不知道子進程的退出狀態,會使子進程成爲殭屍進程。

父進程的變量會被複制一份到子進程中,變量在子進程中的任何修改不會影響父進程中的變量。
相關文章
相關標籤/搜索