В чем разница между этими четырьмя командами (fifo, замена процесса, перенаправление...)

В чем разница между этими четырьмя командами (fifo, замена процесса, перенаправление...)

Моя цель — создать простой эхо-сервер, используя ncи один fifo. Я не ищу лучший способ сделать это, я просто пытаюсь понять семантику следующих команд (когда происходит fork, почему, что он меняет, почему команды ведут себя по-разному...).

Я использую Bash, поэтому не уверен, что все команды будут работать с POSIX shили zsh, ksh, ...

Вот четыре команды, которые я упоминаю в заголовке (предполагая, что я это уже сделал mkfifo fifo):

cat fifo | nc -l localhost 8888 > fifo
exec 3<> fifo && nc -l localhost 8888 <&3 >&3 && exec 3>&-
nc -l localhost 8888 <(cat fifo) > fifo
nc -l localhost 8888 < fifo > fifo

Теперь я ожидаю, что 4 команды будут делать одно и то же, по крайней мере, две последние команды будут делать одно и то же.

  1. Первая команда ведет себя так, как и ожидалось: простой эхо-сервер, который отключается, когда клиент закрывает соединение.
  2. Ведет себя как 1.
  3. Я могу подключиться к серверу, отправить данные, но я никогда ничего не получаю обратно. Когда я закрываю клиентское соединение, сервер выключается.
  4. Невозможно подключиться к серверу, сервер слушает вечно.

решение1

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

человек фифо(7)

Normally, opening the FIFO blocks until the other end is opened also.

В первом случае оболочка разветвляется для выполнения конвейера, поэтому открытие fifo для чтения ( cat fifo) и открытие fifo для записи ( > fifo) происходят в отдельных процессах, то есть независимо.

Во втором случае открытие для чтения и открытие для записи ( 3<>fifo) происходят за один шаг.

В 3-м случае <(cat fifo)расширяется до имени файла, например /dev/fd/42. Так что это похоже на то, что вы запускаете nc -l localhost 8888 /dev/fd/42 > fifo. Вам нужен дополнительный <, чтобы это было эквивалентно, например nc -l localhost 8888 < <(cat fifo) > fifo.

В 4-м случае оболочка пытается открыть fifo для чтения ( < fifo) и открыть его для записи ( > fifo) как часть одного и того же процесса. Оболочка делает это по одному, слева направо. Поэтому она пытается открыть fifoдля чтения и блокируется навсегда, ожидая, пока что-то откроется fifoдля записи. Я думаю, вы обнаружите, что в этом случае ncдаже не начиналось, и порт никогда не открывался для прослушивания.

Связанный контент