Чи є розетка домену FIFO, pipe та Unix те саме в ядрі Linux?


30

Я чув, що ФІФО називають трубами. І вони мають абсолютно таку саму семантику. З іншого боку, я думаю, що сокет домену Unix досить схожий на pipe (хоча я ніколи не використовував його). Тож мені цікаво, чи всі вони посилаються на одну і ту ж реалізацію в ядрі Linux. Будь-яка ідея?


З наведеної нижче відповіді я зрозумів, що моє запитання є неоднозначним, і на нього важко відповісти. Ймовірно, ніхто не міг знати стільки деталей щодо впровадження в ядро ​​(навіть для розробників ядра). Якщо хтось може підтвердити, що сокет домена Unix, pipe та FIFO, вони всі буферують дані, що надсилаються в спільну пам'ять під Linux, моє питання вирішено. Ну ... частково вирішено.
Джастін

FIFO = названі труби! = Труби. FIFO можуть бути двонаправленими, як пара розетки. Регулярні труби односпрямовані. Усі мають інтерфейс файлів та семантику файлів. Чому для вас важлива реалізація?
PSkocik

Я знаю, що труби - це круглі буфери, і що в системі STREAMS вони можуть мати спільну реалізацію, однак Linux не використовує STREAMS за замовчуванням. Я вважаю, що жорсткі коди Linux ці IPC-канали. Я не хочу перевіряти. : D Чому ти не підеш? Код є загальнодоступним.
PSkocik

Якщо всі вони поділяють однакову реалізацію, їх ефективність повинна бути близькою одна до одної. І, на мене, код ядра занадто важко зрозуміти.
Джастін

Відповіді:


35

Розетки домену UNIX та FIFO можуть поділяти частину їхньої реалізації, але вони концептуально відрізняються. FIFO функціонує на дуже низькому рівні. Один процес записує байти в трубу, а інший читає з нього. Розетка домену UNIX має таку саму поведінку, як і сокет TCP / IP.

Розетка є двонаправленою і може використовуватись у багатьох процесах одночасно. Процес може приймати безліч з'єднань одного і того ж сокета і відвідувати декілька клієнтів одночасно. Ядро кожного разу постачає новий дескриптор файлу connect(2)або accept(2)викликається в сокет. Пакети завжди йдуть до потрібного процесу.
У FIFO це було б неможливо. Для двосторонньої комунікації вам потрібно два FIFO, і вам потрібна пара FIFO для кожного з ваших клієнтів. Немає можливості писати чи читати вибірково, адже вони є набагато примітивнішим способом спілкування.

Анонімні труби та FIFO дуже схожі. Різниця полягає в тому, що анонімні канали не існують як файли у файловій системі, тому жоден процес не може open(2)цього зробити. Вони використовуються процесами, які поділяють їх іншим методом. Якщо процес відкриває FIFO, а потім виконує, наприклад, a fork(2), його дитина успадкує його дескриптори файлів і, серед них, трубу.

Розетки домену UNIX, анонімні труби та FIFO подібні тим, що вони використовують сегменти спільної пам'яті. Деталі реалізації можуть відрізнятися від однієї системи до іншої, але ідея завжди однакова: приєднайте одну і ту ж частину пам'яті у двох різних процесах відображення пам'яті, щоб вони мали обмін даними
( редагувати: це був би один очевидний спосіб їх реалізації, але це не те, як це робиться насправді в Linux, який просто використовує пам'ять ядра для буферів, див. відповідь @ tjb63 нижче).
Потім ядро ​​обробляє системні виклики та абстрагує механізм.


"Сокетки домену UNIX та FIFO можуть поділити частину їхньої реалізації" ... справа в тому, "якась частина" ... Я щойно зрозумів, що моє запитання є неоднозначним, і на нього важко відповісти. Ймовірно, ніхто не міг знати стільки деталей, якими частинами вони діляться в ядрі (навіть для розробників ядра). Тим не менш ... чи міг хто-небудь підтвердити, що сокет домену Unix, pipe та FIFO вони всі буферують дані, що надсилаються в спільну пам'ять під Linux? Якщо це підтвердиться, моє питання вирішено. Ну ... частково вирішено.
Джастін

Ну так, є буфер, яким керує ядро. Наприклад, за допомогою FIFO, ви можете вбити письменника, і читач може все-таки те, що було відправлено в трубу до смерті письменника. З розетками це трохи складніше, оскільки вони функціонують із підключеним протоколом. Але якщо ви надішліть, скажімо, int до сокета, а потім вийдете за межі, щоб int очистився від стека відправника, одержувач все ще може його прочитати. Отже, десь явно буфер.
lgeorget

Перечитавши коментар, не впевнений, що я тут зрозумілий ... Повідомте мене, чи є ще щось незрозуміле.
lgeorget

Ваш коментар мені зрозумілий.
Джастін

7

Тут є досить хороша дискусія: http://www.slideshare.net/divyekapoor/linux-kernel-implementation-of-pipes-and-fifos

Наскільки я бачу, як із слайдів презентації, так і з джерела @ http://lxr.free-electrons.com/source/fs/pipe.c - fifo реалізовані як обгортка навколо труби, а самі труби є реалізована через віртуальну файлову систему pipefs ..

@lgeorget - Здається, що в каналах використовується пам'ять ядра для буферів між читачами та записами - вони не використовують "спільну пам'ять" як таку і копіюють пам'ять між адресами та користувачем ядра (наприклад, pipe_readдзвінками pipe_iov_copy_to_user, які викликають __copy_to_user_inatomic(або copy_to_user) . __copy_to_user_inatomicвикликів copy_user_generic, що є кількома реалізаціями ASM.


4

"FIFO" і " названа труба" - це те саме, хоча це зовсім інакше, ніж оболонка обробляє "трубу" (|) між двома командами в командному рядку.

Названа труба (FIFO) - це єдиний "файл", який ділиться двома програмами, де один пише в нього, а другий читає з нього ... Сокет з іншого боку - це "зв'язок" між двома "файлами" - який може використовувати мережу та бути на окремих комп’ютерах - де одна програма читає / записує в один "файл", а інша читає / записує в іншу ... Я не думаю, що вони такі схожі ... З іншого боку обидва розетки та названі труби - а також файли, пристрої, символічні посилання - усі використовують inode, і всі вони реалізують деякі загальні риси (наприклад, читати і записувати).


1
Так, розетка домену Unix є різновидом socket, тому його API схожий з іншими API сокета, такими як TCP або UDP і т. Д. Однак, сокет домену Unix може використовуватися лише як "локальний" IPC. І спосіб передачі даних спочатку спочатку не схожий на FIFO & pipe. Тому я думаю, що можливо, API API сокету домену - це ще одна інкапсуляція ідентичної реалізації, тому ми використовуємо його так, ніби це сокет. Я думаю, що можливо, всі вони мають однакове внутрішнє ядро ... Я хочу підтвердити, правда це чи ні.
Джастін

1

Я не думаю, що Джастін. Якщо я не помиляюся, і я цілком можливо є, я думаю, що FIFO використовують файл на диску, а розетки Unix Domain використовують пам’ять ядра.

Крім того, як додаток до плаката, який вище зазначав, що розетки домену Unix є двонаправленими, це стосується лише випадків використання сокета SOCK_STREAM. SOCK_DGRAM Сокетки домену Unix насправді є однонаправленими і можуть надсилати () лише з коду, який викликав connect (), до коду, який викликав bind ().

Звичайно, код, який викликав connect (), повинен також викликати bind (), щоб створити власну кінцеву точку, але це не має нічого спільного з вашим питанням.


3
Ласкаво просимо на StackExchange і дякуємо за публікацію. Кілька зауважень ... 1) Якщо ви "цілком можливо" помиляєтесь, вам слід двічі перевірити, перш ніж відповісти; цей сайт не є форумом і не спілкується в чаті. 2) Дякую за вашу точність у орієнтованих на дейтаграми розетках 3) Не потрібно публікувати щось, що не має нічого спільного з питанням. :)
lgeorget

1

Мої 2 копійки ... Сокет FIFO та UNIX є двосторонніми (подібними), але сокет має зіркову топологію, тоді як FIFO - це лише черга (і, отже, не можуть замінити один одного), так що їх реалізація може ділитися кодом всередині.

**

char * myfifo = "/tmp/myfifo";
mkfifo(myfifo, 0666);
fd = open(myfifo, O_RDWR);   //so that you can read/write to it
 ...
write(fd, buff1, sizeof(buff1));  
getchar();//wait till some one reds this and writes something else
int sz=read(fd, buff1, sizeof(buff1));  //read that something**

FIFO є двонаправленим?
jhfrontz
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.