Pipe что это
Перейти к содержимому

Pipe что это

  • автор:

Французский [ править ]

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

  • Английский язык
  • Омонимы/en
  • Статьи с 2 омонимами/en
  • Английские существительные
  • Морские термины/en
  • Анатомические термины/en
  • Разговорные выражения/en
  • Ботанические термины/en
  • Термины информатики и компьютерных технологий/en
  • Кулинарные термины/en
  • Американский вариант английского языка
  • Сленговые выражения/en
  • Музыкальные термины/en
  • Жаргонизмы/en
  • Геологические термины/en
  • Электротехнические термины/en
  • Нужно указать гиперонимы/en
  • Требуется категоризация/en
  • Английские глаголы
  • Английские правильные глаголы
  • Металлургические термины/en
  • Шутливые выражения/en
  • Специальные термины/en
  • Слова из 4 букв/en
  • Французский язык
  • Французские существительные
  • Женский род/fr
  • Устаревшие выражения/fr
  • Просторечные выражения/fr
  • Требуется категоризация/fr
  • Слова из 4 букв/fr
  • Бельгийский диалект французского языка
  • Австралийский диалект
  • Нет сведений о составе слова
  • Нужно произношение
  • Статьи со звучащими примерами произношения
  • Нужна иллюстрация
  • Статьи без примеров употребления
  • Нужна этимология
  • Статьи, нуждающиеся в доработке/en
  • Нужны сведения о морфологии/en
  • Нужны сведения о семантике/en
  • Нужна этимология/en
  • Нужны сведения о морфологии/fr
  • Нужна этимология/fr
  • Статьи, нуждающиеся в доработке/fr

Каналы (pipe,fifo)

Каналы — неименованные (pipe) и именованные (fifo) — это средство передачи данных между процессами.

Можно представить себе канал как небольшой кольцевой буфер в ядре операционной системы. С точки зрения процессов, канал выглядит как пара открытых файловых дескрипторов – один на чтение и один на запись (можно больше, но неудобно). Мы можем писать в канал до тех пор пока есть место в буфере, если место в буфере кончится – процесс будет заблокирован на записи. Можем читать из канала пока есть данные в буфере, если данных нет – процесс будет заблокирован на чтении. Если закрыть дескриптор отвечающий за запись, то попытка чтения покажет конец файла. Если закрыть дескриптор отвечающий за чтение, то попытка записи приведет к доставке сигнала SIGPIPE и ошибке EPIPE.

При использовании канала в программировании на языке shell

блокировки чтения/записи обеспечивают синхронизацию скорости выполнения двух программ и их одновременное завершение.

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

Для архитектуры i386 размер буфера, связанного с каналом устанавливают кратным размеру страницы (4096 байт). В Linux в версиях до 2.6.11 использовалась одна страница (4 КБ), после — 16 страниц (65 КБ), с возможностью изменения через fcntl . POSIX определяет значение PIPE_BUF, задающего максимальный размер атомарной записи. В Linux PIPE_BUF равен 4096 байт.

Неименованные каналы

Неименованный канал создается вызовом pipe, который заносит в массив int [2] два дескриптора открытых файлов. fd[0] – открыт на чтение, fd[1] – на запись (вспомните STDIN == 0, STDOUT == 1). Канал уничтожается, когда будут закрыты все файловые дескрипторы ссылающиеся на него.

В рамках одного процесса pipe смысла не имеет, передать информацию о нем в произвольный процесс нельзя (имени нет, а номера файловых дескрипторов в каждом процессе свои). Единственный способ использовать pipe – унаследовать дескрипторы при вызове fork (и последующем exec ). После вызова fork канал окажется открытым на чтение и запись в родительском и дочернем процессе. Т.е. теперь на него будут ссылаться 4 дескриптора. Теперь надо определиться с направлением передачи данных – если надо передавать данные от родителя к потомку, то родитель закрывает дескриптор на чтение, а потомок — дескриптор на запись.

int fd[2]; char c; pipe(fd); if( fork() ) < //родитель close(fd[0]); c=0; while(write(fd[1],&c,1) >0) < c++; >> else < //дочерний процесс dup2(fd[0],0); //подменили STDIN close(fd[0]); close(fd[1]); execl("prog","prog",NULL); //запустили новую программу для которой STDIN = pipe >

Оставлять оба дескриптора незакрытыми плохо по двум причинам:

  1. Родитель после записи не может узнать считал ли дочерний процесс данные, а если считал то сколько. Соответственно, если родитель попробует читать из pipe, то, вполне вероятно, он считает часть собственных данных, которые станут недоступными для потомка.
  2. Если один из процессов завершился или закрыл свои дескрипторы, то второй этого не заметит, так как pipe на его стороне по-прежнему открыт на чтение и на запись.

Если надо организовать двунаправленную передачу данных, то можно создать два pipe.

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

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

Объект FIFO в файловой системе создаётся вызовом функции int mkfifo(const char *pathname, mode_t mode); ,

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

Правила обмена через канал

При обмене данными через канал существуют два особых случая:

  1. Попытка чтения при отсутствии писателей
  2. Попытка записи при отсутствии читателей

Первый случай интерпретируется как конец файла и вызов read вернёт 0. Второй случай не имеет аналогов при работе с обычными файлами, а потому вызывает доставку сигнала SIGPIPE. Программы-фильтры, которые работают с STDOUT по сигналу SIGPIPE обычно завершают работу. Если программа расcчитана на работу с каналами, то для корректной обработки этой ситуации она должна явно изменить стандартный обработчик SIGPIPE, установив его в игнорирование сигнала или переназначив на свою функцию.

Для защиты от этих особых случаев при открытии именованного канала FIFO вызов open() на чтение или на запись блокируется, пока кто-нибудь не откроет канал с другой стороны. Если открывать FIFO с опцией O_NONBLOCK, то одиночное открытие на чтение пройдёт успешно, а попытка открыть на запись FIFO без читателей вернёт ошибку ENXIO (устройство не существует). Открытие FIFO одновременно на чтение и на запись в POSIX не определено. В Linux такой вариант сработает и в блокирующем и в неблокирующем режимах.

Правила обмена через канал

  1. При чтении числа байт, меньшего чем находится в канале, возвращается требуемое число байтов, остаток сохраняется для последующих чтений.
  2. При чтении числа байт, большего чем находится в канале, возвращается доступное число байт.
  3. При чтении из пустого канала, открытого каким либо процессом на на запись при сброшенном флаге O_NONBLOCK произойдёт блокировка процесса, а при установленном флаге O_NONBLOCK будет возвращено -1 и установлено значение errno равное EAGAIN.
  4. Если канал пуст и ни один процесс не открыл его на запись, то при чтении из канала будет получено 0 байтов — т.е конец файла.
  1. Если процесс пытается записать данные в канал, не открытый ни одним процессом на чтение, то процессу отправляется сигнал SIGPIPE. Если не установлена обработка сигнала, то процесс завершается, в противном случае вызов write() возвращает -1 с установкой ошибки EPIPE.
  2. Запись числа байт меньше чем PIPE_BUF выполняется атомарно. При записи из нескольких процессов данные не перемешиваются.
  3. При записи числа байт больше чем PIPE_BUF атомарность операции не гарантируется.
  4. Если флаг O_NONBLOCK не установлен, то запись может быть заблокирована, но в конце концов будет возвращено значение, указывающее, что все байты записаны.
  5. Если флаг O_NONBLOCK установлен и записывается меньше чем PIPE_BUF, то возможны два варианта: если есть достаточно свободного места в буфере, то производится атомарная запись, если нет, то возвращается -1, а errno выставляется в EAGAIN.
  6. Если флаг O_NONBLOCK установлен и записывается больше чем PIPE_BUF то возможны два варианта: если в буфере есть хотя бы один свободный байт, то производится запись доступного числа байт, если нет, то возвращается -1, а errno выставляется в EAGAIN.

Pipe¶

Angular pipe, или просто фильтр, нужен для преобразования данных прямо в HTML-шаблоне. Например, отображение даты и времени в желаемом формате или задание формата вывода числового значения.

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

Рассмотрим пример использования встроенного date pipe.

 1 2 3 4 5 6 7 8 9 10 11 12
@Component( selector: 'date-pipe-example', template: `  Transformed date: >  `, >) export class DatePipeExampleComponent  exampleDate = new Date(2000, 12, 12); > 

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

Некоторые Angular фильтры, как date , принимают параметры, передаваемые после имени фильтра и разделяемые символом : . В данном примере передается формат отображения даты. Подробно со всеми аргументами date можно ознакомиться на официальном сайте.

Ниже приведен список некоторых наиболее часто используемых встроенных Angular pipe:

  • date — преобразование даты;
  • number — преобразование числа;
  • uppercase ( lowercase ) — приведение строкового значения в верхний (нижний) регистр;
  • slice — используется для ограничения вывода информации, в качестве параметров принимает начало и конец интервала отображаемых данных, применяется совместно с директивой *ngFor .

Пример использования slice .

 1 2 3 4 5 6 7 8 9 10 11
@Component( selector: 'slice-pipe-example', template: `  >  `, >) export class SlicePipeExampleComponent  list = ['Jack', 'Alice', 'Michael']; > 

Отсчет выводимых элементов, как и индекс, начинается с нуля.

Полный список встроенных Angular pipe также можно найти в документации.

К одному значению допустимо одновременное применение нескольких фильтров.

Встроенные фильтры подходят в основном для решения «базовых» задач. Поэтому часто требуется создавать собственные (Angular custom pipe).

Рассмотрим на примере создание cutTextPipe , который обрезает слово, если его длина превышает заданное количество символов, и добавляет в конце многоточие.

 1 2 3 4 5 6 7 8 9 10 11
@Pipe( name: 'cutText' >) export class CutTextPipe implements PipeTransform  transform( value: string, maxLength: number = 200 ): string  if (value.length > maxLength) return `$value.substring(0, maxLength)>. `; else return value; > > 

Angular pipe — это класс, который предваряется декоратором @Pipe() и реализует интерфейс PipeTransform с одним единственным методом transform() .

В примере декоратору в качестве аргумента передается объект со свойством name , значение которого является именем фильтра. Именно по нему он будет вызываться в HTML-шаблоне.

Метод transform() в качестве первого аргумента принимает преобразуемое значение, далее — параметры в порядке их передачи в HTML-шаблоне. Метод обязательно должен возвращать итоговое значение.

Как и компоненты, фильтры должны объявляться в свойстве declarations того модуля, в котором они будут использоваться.

Pure & Impure Angular pipes¶

Различают два типа фильтров: pure (по умолчанию) и impure .

Отличаются они по принципу работы механизма отслеживания изменений.

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

Выражение с примененным к нему фильтром второго типа ( impure ) будет обновляться при любом изменении данных, а также в ответ на любое фиксирующееся в приложении событие, например, клик мыши.

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

Для создания impure pipe в объекте, передаваемому декоратору, необходимо указать значение свойства pure false.

1 2 3 4
@Pipe( name: 'cutText', pure: false >) 

Создавать impure Angular pipe следует в исключительных случаях, поскольку такое частое обновление значения выражения требует больших ресурсов.

Конвейер (pipe) — перенаправление ввода-вывода в Linux

Простым примером перенаправления является pipe (конвейер). Обозначается он символом | (прямая палочка, кто не понял 🙂 ). Используется pipe следующим образом:

команда 1 | команда 2 | команда 3 . 

При таком вызове все данные, которые при обычном запуске команды 1 выводились бы на экран будут поступать на стандартный ввод команды 2, как будто бы мы вводим эти данные с клавиатуры.

Поясню на примере. Введите команду ls -l / . Вы увидите как на экран будет выведено содержимое корневого каталога.

Теперь давайте перенаправим вывод этой команды на ввод другой команды: grep , которая ищет во входных данных некоторое сочетание символов. Например, используем такую команду: ls -l / | grep tmp .

Объясню поподробнее что это значит: команда ls -l / Выведет содержимое корневого каталога (как мы убедились выше). Дальше данные поступают команде grep tmp , которая произведет поиск по входным данным (полученным из 1 команды). После чего команда grep выведет то, что нашла на экран (разумеется, это дело опять можно перенаправить).

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

Если проводить ассоциации с реальным миром, то можно представить pipe в виде длинной трубы, распооженной вертикально (что-то мне подсказывает, что разработчики системы преставляли себе это именно также, потому и выбрали такое название и символ |). В эту трубу некто (команда 1) сверху кидает яблоки (данные). Второй некто (команда 2) достает из трубы эти яблоки. Ширина трубы не позволяет яблакам менять порядок, то есть в каком порядке они были отправлены командой 1, в таком порядке они будут приняты командой 2. Скорости работы команд также могут различаться. В случаи, если второй некто замешкается, яблоки будут оставаться в трубе, дожидаясь обработки. Если замешкается первый, то второй будет ждать поступления данных.

Пожалуй, это все, что можно сказать про конвейер в Linux.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *