Каковы гарантии для одновременной записи в именованный канал?

32

Например, я создал именованный канал, как показано ниже:

mknod myPipe p

И я читаю из него какой-то процесс (например, какой-то сервер). В качестве примера я использовал tail:

tail -f myPipe

Если несколько клиентских процессов записывают в него несколько сообщений (например echo "msg" >> myPipe, есть ли вероятность, что сообщения будут чередоваться, например так:

 <beginning of message1><message2><ending of message1>

Или процесс записи в именованный канал атомарный?

Рогач
источник

Ответы:

29

Это зависит от того, сколько пишет каждый процесс (при условии, что ваша ОС в этом отношении совместима с POSIX). От write():

Запросы на запись в канал или FIFO должны обрабатываться так же, как и обычный файл, со следующими исключениями:
[...]

  • Запросы на запись байтов {PIPE_BUF} или меньше не должны чередоваться с данными из других процессов, выполняющих запись в том же канале. При записи более байтов {PIPE_BUF} данные могут чередоваться на произвольных границах с записью другими процессами независимо от того, установлен или нет флаг O_NONBLOCK флагов состояния файла.

Кроме того, в Обоснование раздела в отношении труб и FIFOs:

  • Атомарный / неатомарный : запись является атомарной, если вся сумма, записанная в одной операции, не чередуется с данными из любого другого процесса. Это полезно, когда несколько писателей отправляют данные одному читателю. Приложения должны знать, насколько большой запрос на запись может быть выполнен атомарно. Этот максимум называется {PIPE_BUF}. Этот том POSIX.1-2008 не говорит о том, являются ли запросы записи для более чем {PIPE_BUF} байтов атомарными, но требует, чтобы записи {PIPE_BUF} или меньше байтов были атомарными.

Значение if PIPE_BUFопределяется каждой реализацией, но минимум составляет 512 байт (см. limits.h). В Linux это 4096 байт (см. pipe(7)).

Мат
источник
5
Между прочим, PIPE_BUF гарантированно будет по крайней мере 512. Обратите внимание, что вы также должны гарантировать, что ваш процесс фактически записывает каждую строку в него за один вызов write. Включение буферизации строки ( setvbuf(stdout, NULL, _IOLBF,512)) сделает это без необходимости использования низкоуровневых функций.
Random832
Вот таблица наблюдаемых PIPE_BUFзначений в распространенных системах Unix: ar.to/notes/posix#pipe-buf
Arto Bendiken
Я не понимаю, как сокеты могут быть мультиплексированы ... но именованные каналы не могут ?? все в unix это просто файл, верно? lulz
Александр Миллс
@AlexanderMills: я не понимаю ваш комментарий
Мат
1
@AlexanderMills: нет, это минимальное значение
Мат