日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

eval并发 shell_Shell 实现多任务并发

發(fā)布時(shí)間:2025/3/15 编程问答 57 豆豆
生活随笔 收集整理的這篇文章主要介紹了 eval并发 shell_Shell 实现多任务并发 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

實(shí)現(xiàn)思路

實(shí)現(xiàn)一個(gè)shell進(jìn)程庫(kù),通過類似于init,run,wait幾個(gè)簡(jiǎn)單的命令,就可以迅速實(shí)現(xiàn)多進(jìn)程并發(fā),偽碼如下:

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

原理解析

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

管道

主要思路:通過mkfifo創(chuàng)建一個(gè)有名管道,將管道與一個(gè)文件描述符綁定,通過往管道中寫數(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)文件描述符

# 測(cè)試

exec8>file

echo "hello word!" 1>&8

eval

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

file_fd=8exec ${file_fd}>file

# 測(cè)試

bash test.shtest.sh: line 7: exec: 8: not found

原因:shell在重定向操作符()左邊不進(jìn)行變量展開。因而引入eval命令,強(qiáng)制shell進(jìn)行變量展開。

eval exec "${fd}>file"簡(jiǎn)單的說,eval將右邊參數(shù)整體作為一個(gè)命令,進(jìn)行變量的替換,然后將替換后的輸出結(jié)果給shell去執(zhí)行。

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

命令執(zhí)行

functionprocess_run()

{

cmd=$1

if [ -z "$cmd" ]; then

echo "please input command to run"_delete_pipe

exit1

fi_process_get

{

$cmd

_process_post

}&}

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

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

chengsun@153_92:~/test> bash process_util.shchengsun@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的時(shí)候,創(chuàng)建一個(gè)shell進(jìn)程,相當(dāng)于爺爺被創(chuàng)建起來,而遇到{ command1; command2 } &時(shí),shell 又創(chuàng)建一個(gè)子shell進(jìn)程(爸爸進(jìn)程)處理命令序列;而對(duì)于每一個(gè)外部命令,shell都會(huì)創(chuàng)建一個(gè)子進(jìn)程運(yùn)行該命令,即兒子進(jìn)程被創(chuàng)建。

困惑:為什么處理{ command1; command2; } &需要單獨(dú)創(chuàng)建子進(jìn)程?

按照bash manual說法,{ list }并不會(huì)創(chuàng)建一個(gè)新的shell來運(yùn)行命令序列。但由于加入&,代表將命令族放入后臺(tái)執(zhí)行,就必須新開subshell,否則shell會(huì)阻塞。

進(jìn)程組

chengsun@153_92:~/test> ps -f -e -o pid,ppid,pgid,comm

PID PPID PGID COMMAND24904 21976 24904bash19885 24904 19885\_ bash # 爺爺19893 19885 19885\_ bash # 爸爸19894 19893 19885 |\_ a.out # 兒子19895 19885 19885\_ bash19896 19895 19885 |\_ a.out19897 19885 19885\_ bash19898 19897 19885 \_ a.out

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

wait

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

清理函數(shù)

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

信號(hào)

trap

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

functionPrint

{echo "Hello World!"}

trap Print SIGKILL

kill

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

void sig_handler(intsigno)

{

printf("sigterm signal\n");

}intmain()

{

signal(SIGTERM, sig_handler);sleep(100);

return0;

}

chengsun@153_92:~/test> ./a.out &[1] 19254chengsun@153_92:~/test> kill 19254sigterm signal

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

chengsun@153_92:~/test> man kill

0 All processes in the current process group are signaled.

清理

function_clean_up

{

# 清理管道文件

_delete_pipekill 0

kill -9$$

}

trap _clean_up SIGINT SIGHUP SIGTERM SIGKILL

kill -9 $$?非常重要

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

使用范例

# file: run.sh#!/bin/sh#load process library

source ./process_util.sh

functionhandler()

{

city=$1./main ${city}

}

process_init23

for city in$citiesdocmd= "handler $city"process_run"$cmd"

doneprocess_wait

————————————————

版權(quán)聲明:本文為CSDN博主「spch2008」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/spch2008/article/details/51433353

喜歡這篇文章?歡迎打賞~~

總結(jié)

以上是生活随笔為你收集整理的eval并发 shell_Shell 实现多任务并发的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。