Являются ли сокеты FIFO, pipe и Unix одинаковыми в ядре Linux?

30

Я слышал, что FIFO - это именованные каналы. И у них точно такая же семантика. С другой стороны, я думаю, что доменный сокет Unix очень похож на pipe (хотя я никогда не использовал его). Поэтому мне интересно, все ли они ссылаются на одну и ту же реализацию в ядре Linux. Есть идеи?

Джастин
источник
Из ответа ниже я понял, что мой вопрос довольно двусмысленный, и на него трудно ответить. Скорее всего, никто не мог знать так много деталей о реализации в ядре (даже для разработчиков ядра). Если кто-то может подтвердить, что сокет домена Unix, канал и 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 ниже).
Затем ядро ​​обрабатывает системные вызовы и абстрагирует механизм.

lgeorget
источник
«Доменные сокеты UNIX и FIFO могут разделять некоторую часть их реализации» ... суть в «некоторой части» ... Я только что понял, что мой вопрос является двусмысленным, и на него трудно ответить. Вероятно, никто не мог знать так много деталей о том, какие части они разделяют в ядре (даже для разработчиков ядра). Тем не менее ... кто-нибудь может подтвердить, что сокет домена Unix, канал и 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 реализованы как обертка вокруг pipe, а сами pipe - реализовано через виртуальную файловую систему pipefs ..

@lgeorget - каналы, по-видимому, используют память ядра для буферов между считывателями и авторами - они не используют «разделяемую память» как таковую и копируют память между адресными пространствами пользователя и ядра (например, pipe_readвызовы pipe_iov_copy_to_user, которые вызывают __copy_to_user_inatomic(или copy_to_user) . __copy_to_user_inatomicвызовы copy_user_generic, отражаемый на несколько реализаций ASM.

tjb63
источник
4

«FIFO» и « именованный канал» - это одно и то же, хотя и довольно сильно отличается от того, как оболочка обрабатывает «канал» (|) между двумя командами в командной строке.

Именованный канал (FIFO) - это один «файл», совместно используемый двумя программами, где одна пишет в него, а другая читает из него ... Сокет, с другой стороны, представляет собой «соединение» между двумя «файлами», которое может использовать сеть и находиться на разных компьютерах - где одна программа читает / пишет в один "файл", а другая программа читает / пишет в другой ... Я не думаю, что они похожи ... С другой стороны, оба сокеты и именованные каналы - а также файлы, устройства, символические ссылки - все используют inode, и все они реализуют некоторые общие функции (такие как чтение и запись).

Баард Копперуд
источник
1
Да, сокет домена Unix является своего рода сокетом, поэтому его API похож на другие API сокетов, такие как TCP или UDP и т. Д. Однако сокет домена Unix можно использовать только как «локальный» IPC. И то, как они передают данные, в первую очередь, во многом как FIFO & pipe. Поэтому я думаю, что API-интерфейс доменного сокета Unix - это просто еще одна инкапсуляция идентичной реализации, поэтому мы используем его, как если бы это был сокет. Я думаю, возможно, что они все имеют одинаковые внутренние компоненты в ядре ... Я хочу подтвердить, правда это или нет.
Джастин
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