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

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

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

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

Анонимные трубы и FIFO очень похожи. Разница в том, что анонимные каналы не существуют как файлы в файловой системе, поэтому процесс не может open(2) . Они используются процессами, которые используют их другим способом. Если процесс открывает FIFO, а затем, например, fork(2) , его сын наследует свои файловые дескрипторы и среди них – канал.

Сокеты домена UNIX, анонимные каналы и FIFO похожи на то, что они используют сегменты разделяемой памяти. Детали реализации могут варьироваться от одной системы к другой, но идея всегда одна и та же: добавьте одну и ту же часть памяти в два разных отображения памяти процессов, чтобы они делили данные (редактирование: это один из очевидных способов ее реализации, но это а не как это делается в Linux, который просто использует память ядра для буферов, см. ответ на @ tjb63 ниже). Затем ядро ​​обрабатывает системные вызовы и абстрагирует механизм.

Об этом неплохо говорят: 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 , который copy_user_generic несколькими реализациями ASM.

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

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

Я так не думаю, Джастин. Если я не ошибаюсь, и я вполне возможно, я думаю, что FIFO использует файл на диске, а сокеты Unix домена используют память ядра.

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

Конечно, код, который вызвал connect (), также должен вызвать bind () для создания собственной конечной точки, но это не имеет никакого отношения к вашему вопросу.