Słyszałem, że FIFO są nazwane fajkami. I mają dokładnie taką samą semantykę. Z drugiej strony, myślę, że gniazdo domeny Unix jest dość podobne do potoku (chociaż nigdy z niego nie korzystałem). Zastanawiam się więc, czy wszystkie odnoszą się do tej samej implementacji w jądrze Linuksa. Dowolny pomysł?
30
Odpowiedzi:
Gniazda domen UNIX i FIFO mogą współdzielić część ich implementacji, ale pod względem koncepcyjnym są bardzo różne. FIFO działa na bardzo niskim poziomie. Jeden proces zapisuje bajty do potoku, a inny odczytuje z niego. Gniazdo domeny UNIX zachowuje się tak samo jak gniazdo TCP / IP.
Gniazdo jest dwukierunkowe i może być używane przez wiele procesów jednocześnie. Proces może przyjmować wiele połączeń na tym samym gnieździe i jednocześnie obsługiwać kilku klientów. Jądro dostarcza nowy deskryptor pliku za każdym razem
connect(2)
lubaccept(2)
jest wywoływane w gnieździe. Pakiety zawsze przejdą do właściwego procesu.W przypadku FIFO byłoby to niemożliwe. Do komunikacji dwukierunkowej potrzebujesz dwóch FIFO i pary FIFO dla każdego z Twoich klientów. Nie ma możliwości pisania lub czytania w sposób selektywny, ponieważ są one znacznie bardziej prymitywnym sposobem komunikacji.
Anonimowe potoki i FIFO są bardzo podobne. Różnica polega na tym, że anonimowe potoki nie istnieją jako pliki w systemie plików, więc żaden proces nie może
open(2)
tego zrobić. Są używane przez procesy, które współużytkują je w inny sposób. Jeśli proces otworzy FIFO, a następnie wykona na przykład afork(2)
, jego dziecko odziedziczy deskryptory plików, a wśród nich potok.Gniazda domen UNIX, anonimowe potoki i FIFO są podobne, ponieważ używają segmentów pamięci dzielonej. Szczegóły implementacji mogą się różnić w zależności od systemu, ale idea jest zawsze taka sama:
dołącz tę samą część pamięci w dwóch odrębnych procesach mapowania pamięci, aby współdzieliły dane( edytuj: to byłby oczywisty sposób na wdrożenie, ale to jest nie jak to jest faktycznie zrobione w Linuksie, który po prostu wykorzystuje pamięć jądra dla buforów, patrz odpowiedź @ tjb63 poniżej).
Jądro następnie obsługuje wywołania systemowe i wyodrębnia mechanizm.
źródło
Całkiem niezła dyskusja na ten temat: http://www.slideshare.net/divyekapoor/linux-kernel-implementation-of-pipes-and-fifos
O ile widzę, zarówno ze slajdów prezentacji, jak i źródła @ http://lxr.free-electrons.com/source/fs/pipe.c - fifo są zaimplementowane jako owijanie wokół rur, a same rury są zaimplementowane przez wirtualny system plików pipefs.
@lgeorget - Wydaje się, że potoki używają pamięci jądra do buforowania między czytnikami a programami zapisującymi - nie używają „pamięci współużytkowanej” jako takiej i kopiują pamięć między przestrzenią adresową użytkownika a jądrem (np.
pipe_read
wywołaniapipe_iov_copy_to_user
, które wywołują__copy_to_user_inatomic
(lubcopy_to_user
) ,__copy_to_user_inatomic
wywołujecopy_user_generic
, który jest jednym z kilku wdrożeń ASM.źródło
„FIFO” i „ nazwany potok” to to samo - choć jest to całkiem odmienne od tego, jak powłoka obsługuje „potok” (|) między dwoma poleceniami w wierszu poleceń.
Nazwany potok (FIFO) to pojedynczy „plik” współdzielony przez dwa programy, z których jeden zapisuje do niego, a drugi odczytuje z niego… Z drugiej strony gniazdo to „połączenie” między dwoma „plikami” - co może korzystać z sieci i znajdować się na osobnych komputerach - gdzie jeden program odczytuje / zapisuje do jednego „pliku”, a inny program odczytuje / zapisuje do drugiego ... Nie sądzę, że są do siebie podobne… Z drugiej strony oba gniazda i nazwane potoki - a także pliki, urządzenia, dowiązania symboliczne - wszystkie używają i-węzłów i wszystkie implementują niektóre typowe funkcje (takie jak odczyt i zapis).
źródło
Nie wydaje mi się, Justin. Jeśli się nie mylę i całkiem możliwe, myślę, że FIFO używają pliku na dysku, a gniazda Domeny Unix używają pamięci jądra.
Ponadto, jako dodatek do powyższego plakatu, który wspomniał, że gniazda domenowe Unix są dwukierunkowe, tak jest tylko w przypadku korzystania z gniazda SOCK_STREAM. SOCK_DGRAM Gniazda domeny Unix są w rzeczywistości jednokierunkowe i mogą wysyłać () tylko z kodu, który wywołał connect (), do kodu, który wywołał bind ().
Oczywiście kod, który wywołał connect (), musi również wywołać bind (), aby utworzyć własny punkt końcowy, ale nie ma to nic wspólnego z twoim pytaniem.
źródło
Moje 2 centy ... Gniazdo FIFO i UNIX są dwukierunkowe (podobne), ale gniazdo ma topologię gwiazdy, podczas gdy FIFO jest tylko kolejką (i dlatego nie może się zastąpić), tak, ich implementacja może współdzielić kod wewnętrznie.
**
źródło