Jakie są gwarancje dla równoczesnych zapisów w nazwanym potoku?

32

Na przykład utworzyłem nazwany potok podobny do następującego:

mknod myPipe p

I czytam z niego z jakiegoś procesu (na przykład z jakiegoś serwera). Na przykład użyłem ogona:

tail -f myPipe

Jeśli kilka procesów klienckich zapisuje w nim niektóre wiadomości (na przykład echo "msg" >> myPipe, czy istnieje szansa, że ​​wiadomości zostaną przeplecione, tak jak poniżej:

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

Czy proces pisania do nazwanego potoku jest atomowy?

Rogach
źródło

Odpowiedzi:

29

Zależy to od tego, ile piszą poszczególne procesy (zakładając, że twój system operacyjny jest pod tym względem zgodny z POSIX). Od write():

Żądania zapisu do potoku lub FIFO będą obsługiwane w taki sam sposób, jak zwykły plik, z następującymi wyjątkami:
[...]

  • Żądania zapisu o wielkości {PIPE_BUF} lub mniejszej nie będą przeplatane z danymi z innych procesów wykonujących zapisy na tym samym potoku. Zapisy większe niż {PIPE_BUF} mogą mieć dane przeplatane, na dowolnych granicach, zapisami innych procesów, niezależnie od tego, czy ustawiona jest flaga O_NONBLOCK flag statusu pliku.

Również w sekcji uzasadnienia dotyczącej rur i FIFO:

  • Atomowy / nieatomowy : zapis jest atomowy, jeśli cała ilość zapisana w jednej operacji nie jest przeplatana z danymi z innego procesu. Jest to przydatne, gdy wielu pisarzy wysyła dane do jednego czytnika. Aplikacje muszą wiedzieć, jak duże może być wykonanie atomowe. To maksimum nazywa się {PIPE_BUF}. Ten tom POSIX.1-2008 nie mówi, czy żądania zapisu dla więcej niż {PIPE_BUF} bajtów są atomowe, ale wymaga, aby zapisy {PIPE_BUF} lub mniej bajtów były atomowe.

Wartość if PIPE_BUFjest definiowana przez każdą implementację, ale minimum to 512 bajtów (patrz limits.h). W systemie Linux jest to 4096 bajtów (patrz pipe(7)).

Mata
źródło
5
Nawiasem mówiąc, PIPE_BUF ma gwarancję co najmniej 512. Pamiętaj, że musisz również zagwarantować, że proces faktycznie zapisuje każdą linię do niego w jednym wywołaniu zapisu. Włączenie buforowania linii ( setvbuf(stdout, NULL, _IOLBF,512)) spowoduje to bez konieczności korzystania z funkcji niskiego poziomu.
Random832,
Oto tabela obserwowanych PIPE_BUFwartości na popularnych systemach uniksowych: ar.to/notes/posix#pipe-buf
Arto Bendiken
Nie rozumiem, jak gniazda mogą być multipleksowane ... ale nazwane potoki nie mogą? wszystko na Uniksie to tylko plik, prawda? lulz
Alexander Mills,
@AlexanderMills: Nie rozumiem twojego komentarza
Mat.
1
@AlexanderMills: nie, to minimalna wartość
Mat.