欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Shell 實現(xiàn)多任務(wù)并發(fā)的示例代碼

 更新時間:2023年06月20日 09:08:58   作者:普通網(wǎng)友  
本文主要介紹了Shell 實現(xiàn)多任務(wù)并發(fā)的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

實現(xiàn)思路

實現(xiàn)一個shell進(jìn)程庫,通過類似于initrun,wait幾個簡單的命令,就可以迅速實現(xiàn)多進(jìn)程并發(fā),偽碼如下:

process_init # 創(chuàng)建進(jìn)程
for city in ${cities[*]}
do
    cmd="handler $city"
    process_run $cmd 
done
process_wait # 等待進(jìn)程

原理解析

在實現(xiàn)C++線程庫的時候,通常會有一個任務(wù)隊列,線程從隊列中取任務(wù)并運(yùn)行。在實現(xiàn)shell進(jìn)程庫的時候,采用了類似原理,通過一個有名管道充當(dāng)任務(wù)隊列。嚴(yán)格來說,并不是一個任務(wù)隊列,而是一個令牌桶。進(jìn)程從桶中取得令牌后才可以運(yùn)行,運(yùn)行結(jié)束后將令牌放回桶中。沒有取得令牌的進(jìn)程不能運(yùn)行。令牌的數(shù)目即允許并發(fā)的最大進(jìn)程數(shù)。

管道

主要思路:通過mkfifo創(chuàng)建一個有名管道,將管道與一個文件描述符綁定,通過往管道中寫數(shù)據(jù)的方式,控制進(jìn)程數(shù)量。

function _create_pipe()
{
    _PROCESS_PIPE_NAME=$(_get_uid)
    mkfifo ${_PROCESS_PIPE_NAME}
    eval exec "${_PROCESS_PIPE_ID}""<>${_PROCESS_PIPE_NAME}"
    for ((i=0; i < $_PROCESS_NUM; i++))
    do
        echo -ne "\n" 1>&${_PROCESS_PIPE_ID}
    done
}

exec

exec fd <  file  #以讀方式打開文件,并關(guān)聯(lián)文件描述符fd
exec fd >  file  #以寫方式打開文件,并關(guān)聯(lián)文件描述符fd
exec fd <> file  #以讀寫方式打開文件,并關(guān)聯(lián)文件描述符
# 測試
exec 8>file
echo "hello word!" 1>&8

eval

為了讓程序有一定的擴(kuò)展性,不想寫死fd,因而引入了變量。

file_fd=8
exec ${file_fd}>file
# 測試
bash test.sh
test.sh: line 7: exec: 8: not found

原因:shell在重定向操作符(<、>)左邊不進(jìn)行變量展開。因而引入eval命令,強(qiáng)制shell進(jìn)行變量展開。 
eval exec "${fd}>file"簡單的說,eval將右邊參數(shù)整體作為一個命令,進(jìn)行變量的替換,然后將替換后的輸出結(jié)果給shell去執(zhí)行。

進(jìn)程關(guān)系

命令執(zhí)行

function process_run()
{
    cmd=$1
    if [ -z "$cmd" ]; then
        echo "please input command to run"
        _delete_pipe    
        exit 1
    fi
    _process_get
    {
        $cmd
        _process_post
    }&
}

_process_get從管道中取得一個令牌,創(chuàng)建一個進(jìn)程執(zhí)行任務(wù),任務(wù)執(zhí)行完畢后,通過_process_post將令牌放回管道。

進(jìn)程創(chuàng)建

chengsun@153_92:~/test> bash process_util.sh
chengsun@153_92:~/test> pstree -a
|`-sshd
|    |-bash
|    |   `-bash process_util.sh         #爺爺
|    |       |-bash process_util.sh     #爸爸
|    |       |   `-a.out                #兒子
|    |       |-bash process_util.sh        
|    |       |   `-a.out                   
|    |       `-bash process_util.sh
|    |           `-a.out

腳本運(yùn)行后,通過pstree命令,得到如上父子進(jìn)程關(guān)系。稍微做一下解釋:當(dāng)運(yùn)行腳本bash process_util.sh的時候,創(chuàng)建一個shell進(jìn)程,相當(dāng)于爺爺被創(chuàng)建起來,而遇到{ command1; command2 } &時,shell 又創(chuàng)建一個子shell進(jìn)程(爸爸進(jìn)程)處理命令序列;而對于每一個外部命令,shell都會創(chuàng)建一個子進(jìn)程運(yùn)行該命令,即兒子進(jìn)程被創(chuàng)建。

困惑:為什么處理{ command1; command2; } &需要單獨(dú)創(chuàng)建子進(jìn)程? 
按照bash manual說法,{ list }并不會創(chuàng)建一個新的shell來運(yùn)行命令序列。但由于加入&,代表將命令族放入后臺執(zhí)行,就必須新開subshell,否則shell會阻塞。

進(jìn)程組

chengsun@153_92:~/test> ps -f -e -o pid,ppid,pgid,comm
 PID  PPID  PGID  COMMAND
24904 21976 24904 bash
19885 24904 19885  \_ bash            # 爺爺
19893 19885 19885      \_ bash        # 爸爸
19894 19893 19885      |   \_ a.out   # 兒子
19895 19885 19885      \_ bash
19896 19895 19885      |   \_ a.out
19897 19885 19885      \_ bash
19898 19897 19885          \_ a.out

Shell 將運(yùn)行process_util的一堆進(jìn)程置于一個進(jìn)程組中。其中爺爺進(jìn)程作為該進(jìn)程組的組長,pid == pgid。

wait

wait pid:阻塞等待某個進(jìn)程結(jié)束; 如果沒有指定參數(shù),wait會等待所有子進(jìn)程結(jié)束。

清理函數(shù)

允許任務(wù)通過CTRL+C方式提前結(jié)束,因而需要清理函數(shù)

信號

trap 
類似C語言signal函數(shù),為shell腳本注冊信號處理函數(shù)。trap arg signals,其中signals為注冊的信號列表,arg為收到信號后執(zhí)行某個命令。

function Print
{
    echo "Hello World!"
}
trap Print SIGKILL

kill 
kill 命令給進(jìn)程或進(jìn)程組發(fā)送信號;kill pid 給進(jìn)程發(fā)送默認(rèn)信號SIGTERM, 通知程序終止執(zhí)行。

void sig_handler(int signo)
{
    printf("sigterm signal\n");
}
int main()
{
    signal(SIGTERM, sig_handler);
    sleep(100);
    return 0;
}
chengsun@153_92:~/test> ./a.out &
[1] 19254
chengsun@153_92:~/test> kill 19254
sigterm signal

kill 0:給當(dāng)前進(jìn)程組發(fā)送默認(rèn)信號SIGTERM

chengsun@153_92:~/test> man kill
0  All processes in the current process group are signaled.

清理

function _clean_up
{
    # 清理管道文件
    _delete_pipe
    kill 0
    kill -9 $$
}
trap _clean_up SIGINT SIGHUP SIGTERM SIGKILL

kill -9 $$ 非常重要

實際上,最上層是爺爺進(jìn)程,當(dāng)發(fā)送Ctrl + C命令的時候,爺爺進(jìn)程捕獲SIGINT信號,調(diào)用_clean_up函數(shù)。爺爺進(jìn)程對整個進(jìn)程組發(fā)送SIGTERM信號,并調(diào)用kill -9結(jié)束自己。爸爸進(jìn)程接收SIGTERM信號,同時也發(fā)送SIGTERN給整個進(jìn)程組,如果沒有kill -9,爸爸進(jìn)程始終無法結(jié)束,進(jìn)入無限遞歸環(huán)節(jié)。兒子為CPP二進(jìn)制程序,內(nèi)部沒有捕獲SIGTERM,該信號默認(rèn)動作是結(jié)束進(jìn)程。

使用范例

# file: run.sh
#!/bin/sh
#load process library
source ./process_util.sh
function handler()
{
    city=$1
    ./main ${city}
}
process_init 23
for city in $cities
do
    cmd = "handler $city"
    process_run "$cmd"
done
process_wait

到此這篇關(guān)于Shell 實現(xiàn)多任務(wù)并發(fā)的示例代碼的文章就介紹到這了,更多相關(guān)Shell 多任務(wù)并發(fā)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Shell腳本避免重復(fù)執(zhí)行的方法

    Shell腳本避免重復(fù)執(zhí)行的方法

    這篇文章主要介紹了Shell腳本避免重復(fù)執(zhí)行的方法的,本文給出的代碼只要放在需要執(zhí)行的腳本頭部即可避免重復(fù)執(zhí)行,非常方便實用,需要的朋友可以參考下
    2015-01-01
  • SHELL腳本read命令的具體用法

    SHELL腳本read命令的具體用法

    這篇文章主要介紹了SHELL腳本read命令的具體用法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • bash獲取當(dāng)前路徑示例

    bash獲取當(dāng)前路徑示例

    這篇文章主要介紹了bash獲取當(dāng)前路徑示例,需要的朋友可以參考下
    2014-04-04
  • Linux Shell 數(shù)組的創(chuàng)建及使用技巧

    Linux Shell 數(shù)組的創(chuàng)建及使用技巧

    這篇文章主要介紹了Linux Shell 數(shù)組的創(chuàng)建及使用技巧,本文講解了數(shù)組定義、數(shù)組讀取與賦值以及特殊使用,需要的朋友可以參考下
    2015-07-07
  • 完美解決gvim的菜單亂碼問題

    完美解決gvim的菜單亂碼問題

    下面小編就為大家?guī)硪黄昝澜鉀Qgvim的菜單亂碼問題。小編覺的挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • linux定時器crontab的使用教程

    linux定時器crontab的使用教程

    這篇文章主要介紹了linux定時器crontab的使用教程,需要的朋友可以參考下
    2018-08-08
  • 在Shell命令行處理JSON數(shù)據(jù)的方法

    在Shell命令行處理JSON數(shù)據(jù)的方法

    這篇文章主要介紹了在Shell命令行處理JSON數(shù)據(jù)的方法,使用jq工具實現(xiàn),需要的朋友可以參考下
    2014-03-03
  • Linux下的tar壓縮解壓縮命令詳解(小結(jié))

    Linux下的tar壓縮解壓縮命令詳解(小結(jié))

    這篇文章給大家分享了linux下的tar 壓縮解壓縮命令,非常不錯,具有參考借鑒價值,需要的朋友參考下
    2017-03-03
  • 使用Bash Shell檢查文件是否存在的方法

    使用Bash Shell檢查文件是否存在的方法

    大多數(shù)情況下,可以使用測試命令來對條件進(jìn)行測試。比如可以比較字符串、判斷文件是否存在及是否可讀等等。下面這篇文章就主要介紹了使用Bash Shell檢查文件是否存在的方法,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-01-01
  • Shell命令中的特殊替換、模式匹配替換、字符串提取和替換的實現(xiàn)

    Shell命令中的特殊替換、模式匹配替換、字符串提取和替換的實現(xiàn)

    本文主要介紹了Shell命令中的特殊替換、模式匹配替換、字符串提取和替換的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03

最新評論