Что такое именованный канал linux

Введение в каналы и именованные каналы в Linux

Оригинал: An introduction to pipes and named pipes in Linux
Автор: Archit Modi
Дата публикации: 23 августа 2018 года
Перевод: А. Кривошей
Дата перевода: апрель 2019 г.

В Linux команда pipe позволяет отправлять вывод одной команды в другую. Каналы, как предполагает термин, могут перенаправлять стандартный вывод, ввод или ошибку одного процесса другому для дальнейшей обработки.

Синтаксис для команды pipe или команды pipe без имени — символ | между любыми двумя командами:

Здесь канал не может быть доступен в другом сеансе; он создается временно, чтобы обеспечить выполнение Command-1 и перенаправить стандартный вывод. Он удаляется после успешного выполнения.

В приведенном выше примере файл contents.txt содержит список всех файлов в определенном каталоге, то есть вывод команды ls -al. Сначала мы подбираем имена файлов с помощью ключевого слова «file» из contents.txt по каналу (как показано), поэтому выходные данные команды cat предоставляются в качестве входных данных для команды grep. Затем мы добавляем канал для выполнения команды awk, которая отображает 9-й столбец из отфильтрованного вывода команды grep. Мы также можем подсчитать количество строк в content.txt с помощью команды wc -l.

Именованный канал может работать, пока система не будет перезагружена, или пока он не будет удален. Это специальный файл, который использует механизм FIFO (первым пришел, первым вышел). Он может использоваться как обычный файл; то есть вы можете писать в него, читать из него, а также открывать или закрывать его. Чтобы создать именованный канал, используется команда:

Она создает файл именованного канала, который можно использовать даже в нескольких сеансах оболочки.

Другой способ создать именованный канал FIFO — использовать следующую команду:

Чтобы перенаправить стандартный вывод любой команды другому процессу, используйте символ >. Чтобы перенаправить стандартный ввод любой команды, используйте символ

Источник

Что такое именованный канал linux

С помощью труб могут общаться только родственные друг другу процессы, полученные с помощью fork (). Именованные каналы FIFO позволяют обмениваться данными с абсолютно «чужим» процессом.

С точки зрения ядра ОС FIFO является одним из вариантов реализации трубы. Системный вызов mkfifo () предоставляет процессу именованную трубу в виде объекта файловой системы. Как и для любого другого объекта, необходимо предоставлять процессам права доступа в FIFO, чтобы определить, кто может писать, и кто может читать данные. Несколько процессов могут записывать или читать FIFO одновременно. Режим работы с FIFO — полудуплексный, т.е. процессы могут общаться в одном из направлений. Типичное применение FIFO — разработка приложений «клиент — сервер».

Синтаксис функции для создания FIFO следующий:

int mkfifo(const char *fifoname, mode_t mode); При возникновении ошибки функция возвращает -1, в противном случае 0. В качестве первого параметра указывается путь, где будет располагаться FIFO. Второй параметр определяет режим работы с FIFO. Пример использования приведен ниже:

int fd_fifo; /*дескриптор FIFO*/

char buffer[]=»Текстовая строка для fifo\n»;

/*Если файл с таким именем существует, удалим его*/

if((mkfifo(«/tmp/fifo0001.1», O_RDWR)) == -1)

fprintf(stderr, «Невозможно создать fifo\n»);

/*Открываем fifo для чтения и записи*/

if((fd_fifo=open(«/tmp/fifo0001.1», O_RDWR)) == — 1)

fprintf(stderr, «Невозможно открыть fifo\n»);

if(read(fd_fifo, &buf, sizeof(buf)) == -1)

fprintf(stderr, «Невозможно прочесть из FIFO\n»);

printf(«Прочитано из FIFO : %s\n»,buf);

Читайте также:  Together ��� mac os

Если в системе отсутствует функция mkfifo (), можно воспользоваться общей функцией для создания файла: int mknod(char *pathname, int mode, int dev);

Здесь pathname указывает обычное имя каталога и имя FIFO. Режим обозначается константой S_IFIFO из заголовочного файла . Здесь же определяются права доступа. Параметр dev не нужен. Пример вызова mknod :

if(mknod(«/tmp/fifo0001.1», S_IFIFO | S_IRUSR | S_IWUSR,

Флаг O_NONBLOCK может использоваться только при доступе для чтения. При попытке открыть FIFO с O_NONBLOCK для записи возникает ошибка открытия. Если FIFO закрыть для записи через close или fclose , это значит, что для чтения в FIFO помещается EOF.

Если несколько процессов пишут в один и тот же FIFO, необходимо обратить внимание на то, чтобы сразу не записывалось больше, чем PIPE_BUF байтов. Это необходимо, чтобы данные не смешивались друг с другом. Установить пределы записи можно следующей программой: #include

/*Создаем новый FIFO*/

if((mkfifo(«fifo0001», O_RDWR)) == -1)

fprintf(stderr, «Невозможно создать FIFO\n»);

printf(«Можно записать в FIFO сразу %ld байтов\n»,

printf(«Одновременно можно открыть %ld FIFO \n»,

При попытке записи в FIFO, который не открыт в данный момент для чтения ни одним процессом, генерируется сигнал SIGPIPE .

В следующем примере организуется обработчик сигнала SIGPIPE , создается FIFO, процесс-потомок записывает данные в этот FIFO, а родитель читает их оттуда. Пример иллюстрирует простое приложение типа «клиент — сервер»:

static volatile sig_atomic_t sflag;

static sigset_t signal_new, signal_old, signal_leer;

static void sigfunc(int sig_nr)

fprintf(stderr, «SIGPIPE вызывает завершение

if(signal(SIGPIPE, sigfunc) == SIG_ERR)

fprintf(stderr, «Невозможно получить сигнал

/*Удаляем все сигналы из множества сигналов*/

/*Устанавливаем signal_new и сохраняем его*/

/* теперь маской сигналов будет signal_old*/

&signal_old) 0) /*Родитель читает из FIFO*/

if (( r_fifo=open(«/tmp/fifo0001.1», O_RDONLY))

Next: Блокировка файлов Up: Трубы (pipes) Previous: Функция popen() Contents 2004-06-22

Источник

Pipes: Программные каналы в Linux

Статья из цикла HuMan

Выбор термина

Какие только термины не используют в русском языке для перевода слова «pipes»: и трубы, и трубопроводы, и конвейеры, и потоки, и прочее. В контексте все эти термины выглядят довольно неуклюже. И вот еще беда — ни от одного из этих существительных нельзя образовать глагол, не говоря уже о том, чтобы называть так символ вертикальной черты. Можно, правда, употребить глагол «конвейеризировать», но такое не написать, не выговорить невозможно. Я пытался делать наметки этой статьи, используя все перечисленные термины, но не был удовлетворен ни одним.

Совершенно случайно, в книге А. Робачевского «Операционная система UNIX» мне встретился термин «программные каналы». Поначалу он показался мне несколько громоздким, но попробовав его на деле, я убедился в его несомненных преимуществах. Он не выглядит смешно и дико как «трубы», от него легко произвести глагол, и, самое главное, он имеет вполне прижившегося на русской почве брата — «именованные каналы», которые никто не назовет «именованными трубопроводами». Итак, решено, в данной статье термин pipes будет звучать как «программные каналы».

Предисловие

Предлагаемая вашему вниманию статья как раз для тех, кто недавно открыл для себя командную строку Линукс.

Введение в программные каналы

Команда dmesg выводит сообщения ядра Линукс о процессе загрузки ОС (те самые, что пробегают по экрану монитора при загрузке системы). Эти сообщения не умещаются на одном экране, и пролетают так быстро, что прочесть их невозможно. Поэтому вывод программы dmesg передают на ввод команде less. (Команда less позволяет выводу команды dmesg заполнить только один экран. Чтобы прочесть следующую порцию текста, нужно нажать клавишу пробела, а чтобы вернуться к предыдущей порции — клавишу b. Прервать работу программы можно клавишей q). Оператором такой передачи служит вертикальная черта (|). (Пробелы до и после вертикальной черты ставятся для удобства чтения, но можно обойтись и без них). Все вместе и есть простейший программный канал.

Читайте также:  Как создать скриншот с windows

Того же результата можно достичь, если сначала перенаправить вывод команды dmesg во временный файл, а затем просмотреть содержимое этого файла на экране монитора.

Очевидно, что такая схема менее производительна: во-первых, необходимо давать две команды, во-вторых потому, что следующая команда может начать работать только после завершения первой.

Необходимо пояснить понятия, которые я походя назвал «вводом» и «выводом» программы.

Любая программа командной оболочки (шелла) оперирует с тремя потоками данных: стандартным вводом (stdin), стандартным выводом (stdout), и стандартным сообщением об ошибке (stderr). (Подробно об этом можно прочесть в статье «Перенаправление стандартных потоков данных»).

По умолчанию, стандартный ввод осуществляется с клавиатуры, а стандартный вывод — на экран монитора. Если же мы задействуем оператор программных каналов (|), то стандартный вывод первой программы станет стандартным вводом второй, при этом на экране монитора он уже не появится.

Такая цепочка вовсе не ограничивается двумя программами, но может продолжаться сколь угодно долго.

Как это работает

Даже если посылающая программа производит 5000 байт в секунду, а принимающая программа может обработать только 100 байт в секунду, все равно никакой потери информации не произойдет, так как программные каналы имеют буферы. Вывод посылающей программы собирается в буфере, ставится в очередь. Когда принимающая программа готова считывать данные, операционная система посылает порцию данных из буфера. В случае переполнения буфера, посылающая программа приостанавливается (блокируется), до тех пор, пока принимающая программа не сможет снова считывать данные, тем самым освобождая буфер.

Механизм этого свойства командной оболочки довольно сложен, в данной статье мы не станем его рассматривать, а будем просто пользоваться этой замечательной способностью шелла.

Как пользоваться программными каналами

Кроме вышеприведенного примера с каналом dmesg | less , часто используется канал ls | less . Команда ls позволяет просматривать содержимое директорий, а с опцией -l дает подробные сведения о файлах, «населяющих» указанную директорию. Если директория содержит достаточно файлов, чтобы их список занял больше одного экрана, то применение программного канала с less или more неизбежно:

Для пробы проделайте такой пример:

Только запаситесь терпением — на моей небольшой системе, установленной с одного CD, в выводе было 87 187 строк, сиречь файлов. Дело в том, что опция -R команды ls выводит содержимое директории рекурсивно, то есть открывая подкаталоги, подкаталоги подкаталогов и так далее, пока не перечислит все файлы. Правда, чтобы просмотреть действительно все файлы в директории, нужно войти как администратор (root), потому что некоторые каталоги могут не давать прав доступа рядовому пользователю.

Понятно, что найти «вручную» что-либо в таком списке проблематично, и тут на помощь снова придут программные каналы.

Команда grep найдет нужные вам строки, если вы зададите образец для поиска:

Обратите внимание на символ # в начале командной строки — он означает, что я вошел с правами суперпользователя.

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

Среди команд-фильтров самая употребительная, без сомнения, grep. Она применяется везде, где нужно выбрать искомое из большого объема данных. Скажем, просмотреть все, что касается USB в выводе команды dmesg:

Это только начало списка строк, выведенных командой grep -i usb , я не привожу его полностью из экономии места. Опция -i приказывает команде grep не замечать разницы между заглавными и строчными буквами.

Любой системный администратор часто пользуется командой ps. С опциями -e и -f она выводит все процессы, текущие в системе в полной форме (подробно). Процессов этих весьма много, поэтому я не привожу полный вывод команды:

Читайте также:  System monitor linux install

Чтобы найти в этом списке интересующие вас процессы, следует канализировать команду ps с командой grep. Допустим, вас интересуют процессы hald:

С таким коротким списком уже легче работать. (Обратите внимание на последнюю строчку, там представлен сам запущенный нами процесс grep hald ).

Другие распространенные команды-фильтры

sort — сортирует строки по алфавиту или порядку номеров

wc — подсчитывает количество строк, слов, байт или символов в тексте

tr — заменяет одни символы другими

sed — позволяет редактировать текст прямо из командной строки, даже не видя его.

cut — вырезает из текста нужные куски и выдает их на стандартный вывод

head/tail — позволяют ограничить просмотр первыми несколькими строками (head — голова), либо последними несколькими строками (tail — хвост).

В этот список я включил только несколько команд-фильтров, освоив которые, можно вдоволь насладиться составлением самых замысловатых программных каналов.

Сложные программные каналы

Примечание: Символ (\) используется для объединения всех шести строк в одну командную строку.

Команда первая: wget получает содержимое HTML web страницы.

Команда вторая: sed удаляет из текста страницы все символы, не являющиеся пробелами или буквами и заменяет их пробелами.

Команда третья: tr переводит все символы верхнего регистра в нижний регистр (заглавные буквы в строчные), а также конвертирует пробелы в строках в символы новой строки, так что теперь каждое «слово» является новой строкой.

Команда четвертая: grep оставляет только строки, содержащие хотя бы один алфавитный символ (попросту букву), удаляя все пустые строки.

Команда пятая: sort сортирует список «слов» в алфавитном порядке, а с опцией -u удаляет дубликаты.

Команда шестая, и последняя: comm находит строки, общие для двух файлов. Первым файлом является стандартный вывод нашего программного канала, для чего вместо имени первого файла стоит прочерк (-), вторым файлом будет файл words.txt. Строки, которые встречаются только во втором файле и те, что встречаются в обоих файлах, подавляются опциями -2 и -3. Результатом будет список слов, встречающихся только в первом файле. И, если считать файл words.txt неким эталонным словарем, то выходящий список будет содержать слова, которых нет в словаре, то есть написанные с ошибками.

Немного истории

Понятие именованного канала

В отличие от анонимного программного канала, автоматически создаваемого шеллом, именованный канал обладает именем, и создается явно при помощи команд mknod или mkfifo. Создадим именованный канал fifo1:

Теперь запустим процесс, обращающийся к данному каналу:

Несмотря на нажатие клавиши ENTER ничего не происходит, что не удивительно, ведь файл fifo1 пока пуст, и команде grep нечего обрабатывать. Однако консоль оказывается занята ждущим процессом, и разблокировать ее можно только прервав процесс (скажем, нажатием клавиш CTRL+c).

Чтобы наполнить именной канал содержимым, нужно чтобы к нему обратился второй процесс. Для этого мы должны открыть вторую консоль и запустить какую-либо команду, передающую данные в файл fifo1. Например:

Немедленно в первой консоли сработает команда grep:

Совершенно ясно, что пользоваться таким неудобным механизмом в пользовательских целях никто не будет, ведь гораздо проще запустить один программный канал:

и получить тот же результат.

Этот пример я привел лишь для демонстрации создания и работы именованного канала. Другое дело, когда именованные каналы создаются самими процессами для обмена информацией друг с другом. Но повторюсь, что тема эта непростая и в данной статье рассматриваться не будет.

Источник

Оцените статью