加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

bash – 关于FIFO和文件描述符的问题

发布时间:2020-12-15 21:00:39 所属栏目:安全 来源:网络整理
导读:我写了一个这样的脚本: N=5FIFO=/tmp/$$.fifomkfifo $FIFOloop(){ for i in $(seq 1 $N); do read tmp $FIFO echo "$i out" done}loop LOOP_PID=$!for i in $(seq 1 $N); do echo $i $FIFO echo "$i in"donewait $LOOP_PID 当我运行脚本时,它停止等待$LOOP_
我写了一个这样的脚本:

N=5
FIFO=/tmp/$$.fifo
mkfifo $FIFO

loop(){
    for i in $(seq 1 $N); do
        read tmp < $FIFO
        echo "$i out"
    done
}

loop &
LOOP_PID=$!
for i in $(seq 1 $N); do
    echo $i > $FIFO
    echo "$i in"
done
wait $LOOP_PID

当我运行脚本时,它停止等待$LOOP_PID并且无法继续.

所以我用文件描述符修改脚本:

N=5
FIFO=/tmp/$$.fifo
mkfifo $FIFO
exec 3<>$FIFO

loop(){
    for i in $(seq 1 $N); do
        read -u3 tmp
        echo "$i out"
    done
}

loop &
LOOP_PID=$!
for i in $(seq 1 $N); do
    echo $i >&3
    echo "$i in"
done
wait $LOOP_PID

还可以.

当我直接使用FIFO时,它无法连续从FIFO中读取数据,它会挂起.当我使用文件描述符时,它没关系.是什么原因?

解决方法

替换这个:

loop(){
    for i in $(seq 1 $N); do
        read tmp < $FIFO
        echo "$i out"
    done
}

有了这个:

loop(){
    for i in $(seq 1 $N); do
        read tmp
        echo "$i out"
    done < $FIFO
}

这使得fifo保持打开状态,而不是每次循环重新打开并重新关闭它.

FIFO非常棘手:

>除非另一个进程准备好从FIFO读取,否则尝试写入FIFO将被阻止.
>如果从FIFO读取的进程关闭FIFO,则任何未读信息都将丢失.

这意味着上述脚本的行为方式可能取决于计时事故.当读取tmp< $FIFO正在执行,有多少行写入FIFO? read将只读取第一个,当FIFO关闭时,其余的将被丢弃. exec语句如何帮助 我们来比较两个脚本.第一个直接使用FIFO:

#!/bin/sh
fifo=/tmp/$$.myfifo
mkfifo "$fifo"
echo $'1n2n3n4'>"$fifo"

for i in {1..4}
do
    read  tmp
    echo $tmp
done <"$fifo"

在等待进程开始读取FIFO时,上述脚本将在第一个回显期间挂起.因为它挂起,所以永远不会到达读取tmp语句,并且此脚本不会产生任何输出.

第二个使用exec来创建文件句柄:

#!/bin/sh
fifo=/tmp/$$.myfifo
mkfifo "$fifo"
exec 3<>"$fifo"
echo $'1n2n3n4'>&3

for i in {1..4}
do
    read -u3 tmp
    echo $tmp
done

此脚本不会挂起并将生成四行输出.不同之处在于shell为文件句柄提供缓冲.因此,当第一个echo语句尝试写入FIFO时,shell已准备好从FIFO读取. shell读取的数据可用于读取-u3 tmp语句.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读