Параллельные записи в mkfifo, похоже, теряются - PullRequest
0 голосов
/ 10 ноября 2018

Я пишу скрипт, который будет настраивать окружение машин.У меня есть возможность поставить скрипт запуска на машины, и поэтому я пытаюсь использовать именованный канал mkfifo в unix на моей машине «рабочей станции», которая будет прослушивать записи с этих новых машин, когда они подключатся.

Проблема в том, что я не могу контролировать, когда эти машины могут появиться в сети.В общей сложности одновременно запущено более 20 машин, и я попытался смоделировать эффекты именованного канала, записываемого несколько раз, прежде чем он сможет прочитать и получить поразительные результаты ....

Я написал два небольших тестовых сценария:

mkfifogen.sh

#!/bin/bash
mkfifo h
testing=""
sleep 10
for((i=0;i<5;i++));do
    echo $I
    while read line;do
       testing+="$line"
    done < h
done

echo "$testing"
rm -f h

и

mkfifowrite.sh

#!/bin/bash
for((i=0;i<5;i++));do
    echo "this is a test $i" > h
done

Когда я запускаю mkfifogen.sh, сопровождаемый mkfifowrite.sh, выводится следующим образом

0
1
2

Затем завершается сценарий mkfifowrite.sh, а сценарий mkfifogen.sh зависает

Затем мне нужно запустить mkfifowrite.Сценарий sh еще 3 раза, и каждый раз это приводит к увеличению приращения вывода в сценарии mkfifogen.sh.При последнем запуске значение тестирования будет выводиться 4 раза, поэтому мой вывод после 4 запусков сценария mkfifowrite.sh и одного из сценариев mkfifogen.sh выглядит следующим образом:

0
1
2
3
4
this is a test 0this is a test 1this is a test 2this is a test 3this is a test 4
this is a test 0this is a test 1this is a test 2this is a test 3this is a test 4
this is a test 0this is a test 1this is a test 2this is a test 3this is a test 4
this is a test 0this is a test 1this is a test 2this is a test 3this is a test 4

Что яЯ ожидаю увидеть после запуска mkfifogen.sh и mkfifowrite.sh, когда каждый из них будет просто:

0
1
2
3
4
this is a test 0this is a test 1this is a test 2this is a test 3this is a test 4

Я немного осмотрелся в Интернете, и есть некоторые загадочные ответы на это, но я не могукажется, из них много смысла.Я чувствую, что эта ссылка может содержать мой ответ, но я не уверен https://unix.stackexchange.com/questions/68146/what-are-guarantees-for-concurrent-writes-into-a-named-pipe

TL; DR:

Как я могу гарантировать, что все записи в именованный канал, независимо от быстрогопоследовательно они выполняются, обрабатываются независимо чтением?

1 Ответ

0 голосов
/ 10 ноября 2018

Считыватель читает до EOF, затем повторяет, пока не будет получено 5 EOF.

Писатель открывает и закрывает трубу 5 раз. Каждый раз, когда писатель закрывает канал, существует потенциальное условие EOF. Он не становится действительным EOF, пока читатель не попытается прочитать его (после прочтения всего, что было написано ранее).

Во время этой потенциальной фазы EOF идет гонка. Модуль записи увеличивает i и готовится снова открыть канал для записи, в то время как программа чтения выполняет команду read и обрабатывает результат, после чего он попытается снова прочитать.

Если записывающее устройство выполняет открытое для записи до того, как считывающее устройство пытается выполнить считывание, потенциальное условие EOF исчезает. Если читатель пытается прочитать, когда записывающее устройство больше не подключено к каналу, происходит EOF.

Как вы можете видеть, когда в канал передается несколько пишущих (последовательных или параллельных), EOF - это боль. Вы не можете ожидать, что они будут надежно отображаться между сообщениями разных авторов. Мой выход из этого заключается в том, чтобы спроектировать протокол так, чтобы читателю не требовались EOF для распознавания конца сообщения, а затем чтобы читатель открыл канал в режиме чтения + записи, чтобы всегда быть хотя бы одним существующим писателем, и EOF никогда не произойдет.

Хранение сообщений с размером PIPE_BUF, чтобы они не разбивались, - это отдельная проблема, на которую также следует обратить внимание.

...