Французский [ править ]
Это незаконченная статья. Вы можете помочь проекту, исправив и дополнив её .
В частности, следует уточнить сведения о:
- Английский язык
- Омонимы/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 >
Оставлять оба дескриптора незакрытыми плохо по двум причинам:
- Родитель после записи не может узнать считал ли дочерний процесс данные, а если считал то сколько. Соответственно, если родитель попробует читать из pipe, то, вполне вероятно, он считает часть собственных данных, которые станут недоступными для потомка.
- Если один из процессов завершился или закрыл свои дескрипторы, то второй этого не заметит, так как pipe на его стороне по-прежнему открыт на чтение и на запись.
Если надо организовать двунаправленную передачу данных, то можно создать два pipe.
Именованные каналы
Именованный канал FIFO доступен как объект в файловой системе. При этом, до открытия объекта FIFO на чтение, собственно коммуникационного объекта не создаётся. После открытия открытия объекта FIFO в одном процессе на чтение, а в другом на запись, возникает ситуация полностью эквивалентная использованию неименованного канала.
Объект FIFO в файловой системе создаётся вызовом функции int mkfifo(const char *pathname, mode_t mode); ,
Основное отличие между pipe и FIFO — то, что pipe могут совместно использовать только процессы находящиеся в отношении родительский-дочерний, а FIFO может использовать любая пара процессов.
Правила обмена через канал
При обмене данными через канал существуют два особых случая:
- Попытка чтения при отсутствии писателей
- Попытка записи при отсутствии читателей
Первый случай интерпретируется как конец файла и вызов read вернёт 0. Второй случай не имеет аналогов при работе с обычными файлами, а потому вызывает доставку сигнала SIGPIPE. Программы-фильтры, которые работают с STDOUT по сигналу SIGPIPE обычно завершают работу. Если программа расcчитана на работу с каналами, то для корректной обработки этой ситуации она должна явно изменить стандартный обработчик SIGPIPE, установив его в игнорирование сигнала или переназначив на свою функцию.
Для защиты от этих особых случаев при открытии именованного канала FIFO вызов open() на чтение или на запись блокируется, пока кто-нибудь не откроет канал с другой стороны. Если открывать FIFO с опцией O_NONBLOCK, то одиночное открытие на чтение пройдёт успешно, а попытка открыть на запись FIFO без читателей вернёт ошибку ENXIO (устройство не существует). Открытие FIFO одновременно на чтение и на запись в POSIX не определено. В Linux такой вариант сработает и в блокирующем и в неблокирующем режимах.
Правила обмена через канал
- При чтении числа байт, меньшего чем находится в канале, возвращается требуемое число байтов, остаток сохраняется для последующих чтений.
- При чтении числа байт, большего чем находится в канале, возвращается доступное число байт.
- При чтении из пустого канала, открытого каким либо процессом на на запись при сброшенном флаге O_NONBLOCK произойдёт блокировка процесса, а при установленном флаге O_NONBLOCK будет возвращено -1 и установлено значение errno равное EAGAIN.
- Если канал пуст и ни один процесс не открыл его на запись, то при чтении из канала будет получено 0 байтов — т.е конец файла.
- Если процесс пытается записать данные в канал, не открытый ни одним процессом на чтение, то процессу отправляется сигнал SIGPIPE. Если не установлена обработка сигнала, то процесс завершается, в противном случае вызов write() возвращает -1 с установкой ошибки EPIPE.
- Запись числа байт меньше чем PIPE_BUF выполняется атомарно. При записи из нескольких процессов данные не перемешиваются.
- При записи числа байт больше чем PIPE_BUF атомарность операции не гарантируется.
- Если флаг O_NONBLOCK не установлен, то запись может быть заблокирована, но в конце концов будет возвращено значение, указывающее, что все байты записаны.
- Если флаг O_NONBLOCK установлен и записывается меньше чем PIPE_BUF, то возможны два варианта: если есть достаточно свободного места в буфере, то производится атомарная запись, если нет, то возвращается -1, а errno выставляется в EAGAIN.
- Если флаг 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.