【发布时间】:2013-11-03 17:43:30
【问题描述】:
我正在尝试使用 bash 并行处理文件集。我正在使用命名管道来保持进程数量固定并从进程中收集输出。
我假设对命名管道的写入是原子的,即不同进程的输出不会混淆。这是一个安全的假设吗?
非常感谢任何建议。我仅限于使用 bash。
代码如下:
mytask()
{
wItem=$1
#dummy func; process workItem
rt=$RANDOM
st=$rt;
let "rt %= 2"
let "st %= 10"
sleep $st
return $rt
}
parallelizeTask()
{
workList=$1
threadCnt=$2
task=$3
threadSyncPipeD=$4
outputSyncPipeD=$5
ti=0
for workItem in $workList; do
if [ $ti -lt $threadCnt ]; then
{ $task $workItem; if [ $? == 0 ]; then result="success"; else result="failure"; fi; \
echo "$result:$workItem" >&$outputSyncPipeD; echo "$result:$workItem" >&$threadSyncPipeD; } &
((ti++))
continue;
fi
while read n; do
((ti--))
break;
done <&$threadSyncPipeD
{ $task $workItem; if [ $? == 0 ]; then result="success"; else result="failure"; fi; \
echo "$result:$workItem" >&$outputSyncPipeD; echo "$result:$workItem" >&$threadSyncPipeD;} &
((i++))
done
wait
echo "quit" >&$outputSyncPipeD
while read n; do
if [[ $n == "quit" ]]; then
break;
else
eval $6="\${$6}\ \$n"
fi
done <&$outputSyncPipeD;
}
main()
{
if [ ! -p threadSyncPipe ]; then
mkfifo threadSyncPipe
fi
if [ ! -p outputSyncPipe ]; then
mkfifo outputSyncPipe
fi
exec 4<>threadSyncPipe
exec 3<>outputSyncPipe
gout=
parallelizeTask "f1 f2 f3 f4 f5 f6" 2 mytask 3 4 gout
echo "finalOutput: $gout";
for f in $gout; do
echo $f
done
rm outputSyncPipe
rm threadSyncPipe
}
main
我在以下相关帖子中找到了我的问题的答案。我已经修改了标题以使其更合适。
Are there repercussions to having many processes write to a single reader on a named pipe in posix?
【问题讨论】:
-
你想用简单的英语做什么?您的脚本似乎是一种复杂的方式来执行与 ` echo 'f1\nf2\nf3\nf4\nf5\nf6' | 非常相似的事情。 wargs -n1 -P2 mytask > 痛风`。或者我可能完全错了。
-
术语说明:
bash可以启动多个进程,而不是线程。线程只是一个执行路径,它与单个进程中的其他线程共享其内存。 -
Parallel 或 xargs 也可以帮助您做到这一点。
-
我在相关帖子中找到了答案,根据它,只要写入消息小于页面大小 4k,对 fifo 的写入就是原子的。谢谢大家的回复和建议。 stackoverflow.com/questions/587727/…
-
我同意您找到的答案(需要注意的是,大小是系统配置参数,但 4 KiB 大约是正常大小)。请将其添加为问题的自我回答,然后接受,这样问题就结束了。
标签: multithreading bash named-pipes