Linux write to file pipe

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

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

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

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

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

Предисловие

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Читайте также:  Host файл windows 10 редактирование

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

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

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

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

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

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

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

Чтобы найти в этом списке интересующие вас процессы, следует канализировать команду 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:

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

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

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

Источник

Example of using named pipes in Linux shell (Bash)

Can someone post a simple example of using named pipes in Bash on Linux?

5 Answers 5

One of the best examples of a practical use of a named pipe.

Another useful behavior is using netcat as a proxy. Both ports and hosts can be redirected. Look at this example:

Port 12345 represents the request.

Читайте также:  Сообщение windows устройство usb не опознано

This starts a nc server on port 12345 and all the connections get redirected to google.com:80 . If a web browser makes a request to nc , the request will be sent to google but the response will not be sent to the web browser. That is because pipes are unidirectional. This can be worked around with a named pipe to redirect the input and output.

Here are the commands:

The first command creates the pipe.

The second command writes to the pipe (blocking). The & puts this into the background so you can continue to type commands in the same shell. It will exit when the FIFO is emptied by the next command.

The last command reads from the pipe.

Open two different shells, and leave them side by side. In both, go to the /tmp/ directory:

In the first one type:

In the second one, type:

First shell won’t give you any prompt back until you execute the second part of the code in the second shell. It’s because the fifo read and write is blocking.

You can also have a look at the FIFO type by doing a ls -al myPipe and see the details of this specific type of file.

Next step would be to embark the code in a script!

Creating a named pipe

On Unix-likes named pipe (FIFO) is a special type of file with no content. The mkfifo command creates the pipe on a file system (assigns a name to it), but doesn’t open it. You need to open and close it separately like any other file.

Using a named pipe

Named pipes are useful when you need to pipe from/to multiple processes or if you can’t connect two processes with an anonymous pipe. They can be used in multiple ways:

In parallel with another process:

Here writer runs along the reader allowing real-time communication between processes.

In fact, communication through a pipe can be sequential, but it’s limited to a buffer size of 64 KB.
It’s preferable to use descriptors to transfer multiple pieces of data in order to reduce overhead.

FD allows data transfer to start before the shell is ready to receive it. Required when used sequentially.
Signal should be sent before the data to prevent a deadlock if pipe buffer fills up.

Destroying a named pipe

The pipe itself (and its content) gets destroyed when all descriptors to it are closed. What’s left is just a name.
To make the pipe anonymous and unavailable under the given name (can be done when the pipe is still open) you could use the rm console command (this is the opposite of mkfifo command):

Источник

Что такое каналы (pipe) в Linux? Как работает перенаправление каналов?

Главное меню » Linux » Что такое каналы (pipe) в Linux? Как работает перенаправление каналов?

Вы, вероятно, также знаете, что такое перенаправление канала, которое используется для перенаправления вывода одной команды в качестве ввода для следующей команды.

Но знаете ли вы, что под ним? Как на самом деле работает перенаправление каналов?

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

Примечание. Мы использовали термин Unix в некоторых местах, потому что концепция каналов (как и многие другие вещи в Linux) происходит от Unix.

Каналы в Linux: общая идея

Вот что вы повсюду увидите относительно «что такое каналы в Unix?»:

  • Каналы Unix – это механизм IPC (межпроцессное взаимодействие), который перенаправляет вывод одной программы на вход другой программы.

Это общее объяснение, которое дают все. Мы хотим проникнуть глубже. Давайте перефразируем предыдущую строку более техническим языком, убрав абстракции:

  • Каналы Unix – это механизм IPC (межпроцессного взаимодействия), который принимает программу stdout и пересылает ее другой программе stdin через буфер.

Намного лучше. Удаление абстракции сделало его намного чище и точнее. Вы можете посмотреть на следующую схему, чтобы понять, как работает pipe.

Один из простейших примеров команды pipe – передать некоторый вывод команды команде grep для поиска определенной строки.

Имейте в виду: Pipe перенаправляет стандартный вывод на стандартный ввод, но не как аргумент команды

Очень важно понять, что конвейер передает команду stdout другой команде stdin, но не как аргумент команды. Мы объясним это на примере.

Если вы используете команду cat без аргументов, по умолчанию будет выполняться чтение из stdin. Вот пример:

Здесь мы использовали cat без передачи файлов, поэтому по умолчанию stdin. Затем мы написали строку, а затем использовал Ctrl + d, чтобы сообщить, что закончили писать (Ctrl + d подразумевает EOF или конец файла). Как только мы закончили писать, cat прочитал stdin и написал эту строку в stdout.

Теперь рассмотрим следующую команду:

Вторая команда НЕ эквивалентна cat hey. Здесь stdout”hey” переносится в буфер и передает stdin в cat. Поскольку аргументов командной строки не было, cat по умолчанию выбрал stdin для чтения, а что-то уже было в stdin, поэтому команда cat приняла это и напечатала stdout.

Читайте также:  Запуск этого устройства невозможен код 10 windows 10 звук

Фактически, мы создали файл с именем hey и поместили в него некоторый контент.

Типы каналов в Linux

В Linux есть два типа каналов:

  • Безымянный канал, также называемый анонимным.
  • Именованные каналы

Каналы без названия

Без названия каналы, как следует из названия, не имеют имени. Они создаются на лету вашей оболочкой Unix всякий раз, когда вы используете символ |.

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

Именованные каналы

Этот немного отличается. Именованные каналы действительно присутствуют в файловой системе. Они существуют как обычный файл. Вы можете создать именованный файл, используя следующую команду:

Это создаст файл с именем «pipe». Выполните следующую команду:

Обратите внимание на «p» в начале, это означает, что файл является каналом. Теперь воспользуемся этим каналом.

Как мы говорили ранее, конвейер пересылает вывод одной команды на вход другой. Это как курьерская служба, вы даете посылку доставить с одного адреса, а они доставляют по другому. Итак, первый шаг – предоставить пакет, то есть предоставить каналу что-то.

Вы заметите, что echo еще не вернули нам терминал. Откройте новый терминал и попробуйте прочитать из этого файла.

Обе эти команды завершили свое выполнение одновременно.

Это одно из фундаментальных различий между обычным файлом и именованным каналом. В канал ничего не записывается, пока какой-либо другой процесс не прочитает его.

Зачем использовать именованные каналы? Вот список того, почему вы хотите использовать именованные каналы

Именованные каналы не занимают память на диске

Если вы выполните a du -s pipe, вы увидите, что он не занимает места. Это потому, что именованные каналы похожи на конечные точки для чтения и записи из буфера памяти и в него. Все, что записывается в именованный канал, фактически сохраняется во временном буфере памяти, который сбрасывается, когда операция чтения выполняется из другого процесса.

Сниженный ввод-вывод

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

Связь между двумя очень разными процессами

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

Понимание каналов более низкого уровня [для опытных пользователей и разработчиков]

В следующем разделе речь идет о каналах на более глубоком уровне с фактическими реализациями. Этот раздел требует от вас базового понимания:

  • Как работает программа на C
  • Что такое системные вызовы
  • Что такое процессы
  • Что такое файловые дескрипторы

Мы не будем вдаваться в подробности примеров. Речь идет только о «каналах». Для большинства пользователей Linux этот раздел не нужен.

В конце мы предоставили для компиляции образец файла – Makefile. Имейте в виду, что эти программы предназначены только для иллюстративных целей, поэтому, если вы видите, что ошибки обрабатываются некорректно.

Рассмотрим следующий пример программы:

В строке 16 мы создали безымянный канал, используя функцию pipe(). Первое, что следует заметить, это то, что мы передали массив целых чисел со знаком длиной 2.

Это потому, что канал – это не что иное, как массив из двух целых чисел без знака, представляющих два файловых дескриптора. Один для письма, один для чтения. И оба они указывают на расположение буфера в памяти, которое обычно составляет 1 МБ.

Здесь мы назвали переменную fd. fd [0] – дескриптор входного файла, fd [1] – дескриптор выходного файла. В этой программе один процесс записывает строку в файловый дескриптор fd [1], а другой процесс читает из файлового дескриптора fd [0].

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

Вот пример программы, которая делает то же самое, что и предыдущая программа, но вместо анонимного канала создает именованный канал.

Здесь мы использовали системный вызов mknod для создания именованного канала. Как вы можете видеть, хотя мы удалили канал по завершении, вы вполне можете оставить его и легко использовать для связи между различными программами, просто открыв и записав в файл с именем «npipe» в моем случае.

Вам также не придется создавать два разных канала для двусторонней связи, как в случае с анонимными каналами.

Вот образец Makefile, как и было обещано. Поместите его в тот же каталог, что и предыдущие программы, с именами «pipe.c» и «fifo.c» соответственно.

Вот так. Это действительно все, что есть в каналах Unix.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Источник

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