![连续写入命名管道](https://linux22.com/image/154046/%E8%BF%9E%E7%BB%AD%E5%86%99%E5%85%A5%E5%91%BD%E5%90%8D%E7%AE%A1%E9%81%93.png)
我有一个似乎无法解决的涉及两个命名管道的问题。基本上,我有两个无法控制的流程。他们通过命名管道 ( ) 进行通信mknod pipe p
。进程一是 GPS 驱动程序,以 NMEA0183 格式输出消息。流程二是一个导航应用程序,它读取 NMEA0183 数据以从 GPS 获取位置和日期/时间。我需要调整这个数据(原因:谷歌搜索 WNRO 或询问)。
第一个进程以 1 秒的间隔连续将数据(约 5-8 行文本)写入 /var/run/one.pipe 并将其留在那里直到被读取(?)
第二个进程是从命名管道读取此数据。我可以更改要读取的命名管道的名称。我将其更改为 /var/run/two.pipe
最终目标是从 one.pipe 读取数据,进行一些处理,然后将其传递给 Two.pipe。然而,与此同时,为了进行测试,我只是尝试将数据从 one.pipe 逐一复制到 Two.pipe。我认为在整个处理过程中浪费时间是不可行的,直到我能够完成这个(更简单的?)任务。
一个非常简单的 shell 脚本可以工作:copy.sh
#!/bin/sh
cat one.pipe > two.pipe &
现在我捕获了源进程写入的一些数据one.pipe
,并尝试手动将其写入以two.pipe
供读取进程读取:
#!/bin/sh
while true; do
echo "\$GPGGA,,,,,,,,*12" > two.pipe
echo "\$GPGSA,,,,,,,,*23" > two.pipe
echo "\$GPRMC,,,,,,,,*34" > two.pipe
echo "\$GPGSV,,,,,,,,*45" > two.pipe
echo "\$GPGSV,,,,,,,,*56" > two.pipe
echo "\$GPGSV,,,,,,,,*67" > two.pipe
# checksums (*xx) are just examples here
sleep 1 > two.pipe
done
现在这效果不太好。如果我cat one.pipe
与进行比较,cat two.pipe
我可以看到 中的消息two.pipe
不会“堆积”,而它们是从写入 的原始进程中堆积起来的one.pipe
。例如,如果我启动脚本,它应该写入命名管道并继续这样做。当我用它读取该管道时,cat
应该输出到目前为止的所有数据(假设 fifo 缓冲区尚未填充)。毕竟是先进先出,不是吗?
此外,cat 现在经常看似随机地停止。最后,我无法控制正在读取的进程two.pipe
似乎无法很好地处理数据/导致脚本终止。
我什至不明白为什么脚本会终止,即使它包含无限循环?!
我在这里监视什么?如果用 shell 编写不可行,C 也是一个选择。
答案1
while true; do echo "\$GPGGA,,,,,,,,*12" > two.pipe echo "\$GPGSA,,,,,,,,*23" > two.pipe ...
... > two.pipe
脚本中的每一行都将打开并关闭fifo two.pipe
,关闭它可能会导致从管道另一端的任何读取返回文件结尾,并cat
退出。
我建议一开始就打开fifo一次对于您的整个脚本exec
:
#!/bin/sh
exec > two.pipe
while true; do
echo "\$GPGGA,,,,,,,,*12"
echo "\$GPGSA,,,,,,,,*23"
...
sleep 1
done
您可以通过将 fifo 的两端打开到同一个句柄中来“固定”fifo,例如。
exec 7<>two.fifo
只要执行此操作的进程尚未退出且未关闭文件描述符7
,就可以确保从该文件描述符读取的进程在所有其他句柄处理其文件描述符时不会得到文件结束符。写作SIGPIPE
end 被关闭,并且当所有其他句柄都指向它时,写入它的进程不会被 a 杀死阅读结束已关闭。
此外,同时打开指定 fifo 的两端也不会阻塞。