What is named pipe in linux

What are Named Pipes or FIFO in Linux/Unix systems?

Pipes were meant for communication between related processes. We Cannot use pipes for unrelated process communication. Then to achieve unrelated processes communication, the simple answer is Named Pipes. Even though this works for related processes, it gives no meaning to use the named pipes for related process communication.

Unlike pipe, we can use single named pipe that can be used for two-way communication (communication between the server and the client, plus the client and the server at the same time) as Named Pipe supports bi-directional communication.

Another name for named pipe is FIFO (First-In-First-Out). Let us see the system call (mknod()) to create a named pipe, which is a kind of a special file.

This system call would create a special file or file system node such as ordinary file, device file, or FIFO. The arguments to the system call are pathname, mode and dev. The pathname along with the attributes of mode and device information. The pathname is relative, if the directory is not specified it would be created in the current directory. The mode specified is the mode of file which specifies the file type such as the type of file and the file mode as mentioned in the following tables. The dev field is to specify device information such as major and minor device numbers.

File Type Description File Type Description
S_IFBLK block special S_IFREG Regular file
S_IFCHR character special S_IFDIR Directory
S_IFIFO FIFO special S_IFLNK Symbolic Link
File Mode Description File Mode Description
S_IRWXU Read, write, execute/search by owner S_IWGRP Write permission, group
S_IRUSR Read permission,owler S_IXGRP Execute/search permission, group
S_IWUSR Write permission, owner S_IRWXO Execute/search permission, group
S_IXUSR Execute/search permission, owner S_IROTH Read permission, others
S_IRWXG Read, write, execute/search by group S_IWOTH Write permission, others
S_IRGRP Read permission, group S_IXOTH Execute/search permission, others

File mode can also be represented in octal notation such as 0XYZ, where X represents owner, Y represents group, and Z represents others. The value of X, Y or Z can range from 0 to 7. The values for read, write and execute are 4, 2, 1 respectively. If needed in combination of read, write and execute, then add the values accordingly.

Say, if, 0640, then this means read and write (4 + 2 = 6) for owner, read (4) for group and no permissions (0) for others.

This call would return zero on success and -1 in case of failure. To know the cause of failure, check with errno variable or perror() function.

This library function creates a FIFO special file, which is used for named pipe. The arguments to this function is file name and mode. The file name can be either absolute path or relative path. If full path name (or absolute path) is not given, the file would be created in the current folder of the executing process. The file mode information is as described in mknod() system call.

This call would return zero on success and -1 in case of failure. To know the cause of failure, check with errno variable or perror() function.

Let us consider a program of running the server on one terminal and running the client on another terminal. The program would only perform one-way communication. The client accepts the user input and sends the message to the server, the server prints the message on the output. The process is continued until the user enters the string “end”.

Let us understand this with an example −

Step 1 − Create two processes, one is fifoserver and another one is fifoclient.

Step 2 − Server process performs the following −

Creates a named pipe (using system call mknod()) with name “MYFIFO”, if not created.

Opens the named pipe for read only purposes.

Here, created FIFO with permissions of read and write for Owner. Read for Group and no permissions for Others.

Waits infinitely for message from the Client.

If the message received from the client is not “end”, prints the message. If the message is “end”, closes the fifo and ends the process.

Step 3 − Client process performs the following −

1) Opens the named pipe for write only purposes.

2) Accepts the string from the user.

3) Checks, if the user enters “end” or other than “end”. Either way, it sends a message to the server. However, if the string is “end”, this closes the FIFO and also ends the process.

4) Repeats infinitely until the user enters string “end”.

Two-way Communication Using Named Pipes

The communication between pipes are meant to be unidirectional. Pipes were restricted to one-way communication in general and need at least two pipes for two-way communication. Pipes are meant for inter-related processes only. Pipes can’t be used for unrelated processes communication, say, if we want to execute one process from one terminal and another process from another terminal, it is not possible with pipes. Named pipe is meant for communication between two or more unrelated processes and can also have bi-directional communication.

Already, we have seen the one-directional communication between named pipes, i.e., the messages from the client to the server. Now, let us take a look at the bi-directional communication i.e., the client sending message to the server and the server receiving the message and sending back another message to the client using the same named pipe.

Following is an example −

Step 1 − Create two processes, one is fifoserver_twoway and another one is fifoclient_twoway.

Step 2 − Server process performs the following −

Creates a named pipe (using library function mkfifo()) with name “fifo_twoway” in /tmp directory, if not created.

Opens the named pipe for read and write purposes.

Here, created FIFO with permissions of read and write for Owner. Read for Group and no permissions for Others.

Waits infinitely for a message from the client.

If the message received from the client is not “end”, prints the message and reverses the string. The reversed string is sent back to the client. If the message is “end”, closes the fifo and ends the process.

Step 3 − Client process performs the following −

Opens the named pipe for read and write purposes.

Accepts string from the user.

Checks, if the user enters “end” or other than “end”. Either way, it sends a message to the server. However, if the string is “end”, this closes the FIFO and also ends the process.

If the message is sent as not “end”, it waits for the message (reversed string) from the client and prints the reversed string.

Repeats infinitely until the user enters the string “end”.

Источник

Linux pipes tips & tricks

Pipe — что это?

Pipe (конвеер) – это однонаправленный канал межпроцессного взаимодействия. Термин был придуман Дугласом Макилроем для командной оболочки Unix и назван по аналогии с трубопроводом. Конвейеры чаще всего используются в shell-скриптах для связи нескольких команд путем перенаправления вывода одной команды (stdout) на вход (stdin) последующей, используя символ конвеера ‘|’:

grep выполняет регистронезависимый поиск строки “error” в файле log, но результат поиска не выводится на экран, а перенаправляется на вход (stdin) команды wc, которая в свою очередь выполняет подсчет количества строк.

Логика

Конвеер обеспечивает асинхронное выполнение команд с использованием буферизации ввода/вывода. Таким образом все команды в конвейере работают параллельно, каждая в своем процессе.

Размер буфера начиная с ядра версии 2.6.11 составляет 65536 байт (64Кб) и равен странице памяти в более старых ядрах. При попытке чтения из пустого буфера процесс чтения блокируется до появления данных. Аналогично при попытке записи в заполненный буфер процесс записи будет заблокирован до освобождения необходимого места.
Важно, что несмотря на то, что конвейер оперирует файловыми дескрипторами потоков ввода/вывода, все операции выполняются в памяти, без нагрузки на диск.
Вся информация, приведенная ниже, касается оболочки bash-4.2 и ядра 3.10.10.

Простой дебаг

Исходный код, уровень 1, shell

Т. к. лучшая документация — исходный код, обратимся к нему. Bash использует Yacc для парсинга входных команд и возвращает ‘command_connect()’, когда встречает символ ‘|’.
parse.y:
Также здесь мы видим обработку пары символов ‘|&’, что эквивалентно перенаправлению как stdout, так и stderr в конвеер. Далее обратимся к command_connect():make_cmd.c:
где connector это символ ‘|’ как int. При выполнении последовательности команд (связанных через ‘&’, ‘|’, ‘;’, и т. д.) вызывается execute_connection():execute_cmd.c:

PIPE_IN и PIPE_OUT — файловые дескрипторы, содержащие информацию о входном и выходном потоках. Они могут принимать значение NO_PIPE, которое означает, что I/O является stdin/stdout.
execute_pipeline() довольно объемная функция, имплементация которой содержится в execute_cmd.c. Мы рассмотрим наиболее интересные для нас части.
execute_cmd.c:
Таким образом, bash обрабатывает символ конвейера путем системного вызова pipe() для каждого встретившегося символа ‘|’ и выполняет каждую команду в отдельном процессе с использованием соответствующих файловых дескрипторов в качестве входного и выходного потоков.

Исходный код, уровень 2, ядро

Обратимся к коду ядра и посмотрим на имплементацию функции pipe(). В статье рассматривается ядро версии 3.10.10 stable.
fs/pipe.c (пропущены незначительные для данной статьи участки кода):
Если вы обратили внимание, в коде идет проверка на флаг O_NONBLOCK. Его можно выставить используя операцию F_SETFL в fcntl. Он отвечает за переход в режим без блокировки I/O потоков в конвеере. В этом режиме вместо блокировки процесс чтения/записи в поток будет завершаться с errno кодом EAGAIN.

Максимальный размер блока данных, который будет записан в конвейер, равен одной странице памяти (4Кб) для архитектуры arm:
arch/arm/include/asm/limits.h:
Для ядер >= 2.6.35 можно изменить размер буфера конвейера:
Максимально допустимый размер буфера, как мы видели выше, указан в файле /proc/sys/fs/pipe-max-size.

Tips & trics

В примерах ниже будем выполнять ls на существующую директорию Documents и два несуществующих файла: ./non-existent_file и. /other_non-existent_file.

Перенаправление и stdout, и stderr в pipe

или же можно использовать комбинацию символов ‘|&’ (о ней можно узнать как из документации к оболочке (man bash), так и из исходников выше, где мы разбирали Yacc парсер bash):

Перенаправление _только_ stderr в pipe

Shoot yourself in the foot
Важно соблюдать порядок перенаправления stdout и stderr. Например, комбинация ‘>/dev/null 2>&1′ перенаправит и stdout, и stderr в /dev/null.

Получение корректного кода завершения конвейра

По умолчанию, код завершения конвейера — код завершения последней команды в конвеере. Например, возьмем исходную команду, которая завершается с ненулевым кодом:
И поместим ее в pipe:
Теперь код завершения конвейера — это код завершения команды wc, т.е. 0.

Обычно же нам нужно знать, если в процессе выполнения конвейера произошла ошибка. Для этого следует выставить опцию pipefail, которая указывает оболочке, что код завершения конвейера будет совпадать с первым ненулевым кодом завершения одной из команд конвейера или же нулю в случае, если все команды завершились корректно:
Shoot yourself in the foot
Следует иметь в виду “безобидные” команды, которые могут вернуть не ноль. Это касается не только работы с конвейерами. Например, рассмотрим пример с grep:
Здесь мы печатаем все найденные строки, приписав ‘new_’ в начале каждой строки, либо не печатаем ничего, если ни одной строки нужного формата не нашлось. Проблема в том, что grep завершается с кодом 1, если не было найдено ни одного совпадения, поэтому если в нашем скрипте выставлена опция pipefail, этот пример завершится с кодом 1:
В больших скриптах со сложными конструкциями и длинными конвеерами можно упустить этот момент из виду, что может привести к некорректным результатам.

Источник

named pipes в Unix

Я давно читал про них, ещё когда учился основам юникс, но как-то не было нужды с ними работать. И, вот, нужда возникла.

Некая программа (допустим, foo) не умеет писать вывод в stdout, только в файл. Даже «-» в качестве имени файла всего лишь создаёт файл с названием «-» [большинство умных программ под unix знают, что одиночный минус вместо имени файла означает вывод в stdout]. Аналогично она отвергает и /dev/stdout.

Другая же программа, обрабатывающая результаты первой, допустим, bar, читает из stdin и пишет в stdout. (если быть точным, первое — это трейсер специального вида, дающий двоичный дамп, а второе — конвертор, печатающий их же в человекочитаемом виде).

Нужно их объединить в конвеер.

Некрасивый вариант — использование обычного файла. Записал, прочитал.

Есть куда более красивый вариант — это именованные пайпы. Так как у пайпа есть имя, мы можем передать его как файл первой программе, а потом передать содержимое другой.

Выглядит это так:

Пайп в файловой системе выглядит так:

(акцент на букву ‘p’ первым символом).

Как это работает? Фактически, fifo aka named pipe — это «обыкновенный pipe», примерно такой, который кодируется палкой «|». Однако, у него есть ИМЯ и это имя можно указывать всюду, где требуется файл.

Программа, которая пишет в именованный пайп, ведёт себя с ним как с файлом. Т.е. пишет себе и пишет. Программа, которая читает — аналогично. Читает себе и читает. Чтение идёт в том порядке, как была осуществлена запись (FIFO — first in first out). Положения относительно пайпа (слева/справа) определяются тем, кто читает, а кто пишет.

Важная же особенность пайпа — способность тормознуть читающую/пищущую программу, если буфер пуст/переполнен.

Рассмотрим на примере чтения. Программа пишет в пайп одну строчку в секунду. Программа чтения читает с максимально возможной скоростью. Программа «вычитывает» всё, что было в буфере, и посылает следующий запрос. Ядро этот запрос задерживает до того момента, пока не появятся данные. Таким образом, можно не париться с синхронизацией — появятся данные, программа-обработчик получит управление обратно из read() и обработает очередную порцию данных.

Источник

Читайте также:  Панель задач windows структура
Оцените статью