Добавил:
github.com Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
11
Добавлен:
30.09.2023
Размер:
875.49 Кб
Скачать
    1. Неименованные каналы

Механизм неименованных каналов является удобным инструментом для последовательной передачи данных от процесса к процессу и представляет собой замыкание стандартного вывода stdout одного процесса на стандартный ввод stdin другого процесса. В командной оболочке неименованные каналы между процессами создаются с помощью символа «|», например:

program1 | program2 | program3 | … | programN

Данная команда интерпретируется следующим образом: отправленные процессом «program1» данные в stdout (с помощь, например, функции «printf»), автоматически появятся в stdin у процесса «program2» (которые могут быть считаны с помощью, например, функции «fgets»). В свою очередь данные из stdout процесса «program2» попадут в stdin процесса «program3» и т. д.

Такая организация передачи данных чрезвычайно удобна, когда необходима конвейерная обработка данных, в которой первый процесс выступает источником, а каждый последующий процесс обрабатывает данные предыдущего. Например, если требуется удалить все поддиректории с пометкой «tmp» в рабочей директории, то при вызове команды

ls | grep "tmp" | xargs rm -r

программа «ls» сформирует список существующих файлов и подкаталогов в текущем каталоге, затем программа «grep» оставит из них только те, что содержат в названии подстроку «tmp», а затем программа «xargs» сформирует из них список аргументов для программы «rm», которая их удалит.

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

  • распараллелить stdout процесса-источника на несколько stdin процессов-приемников;

  • отправить в stdin процесса-приемника данные от нескольких процессов-источников;

  • обратиться к промежуточным результатам внутри конвейера: каждое соединение процессов через «|» создают дескрипторы файлов, указывающих на промежуточный буфер, которые доступны только соединенным через них процессам.

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

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

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

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

Во-вторых, данные в именованном канале записываются и считываются по принципу FIFO (First Input First Output), т. е. первыми считываются те данные, которые были записаны первыми, чтение из произвольного места невозможно. После считывания данных любым из процессов они удаляются из именованного канала средствами ОС. Повторно считать данные в именованном канале невозможно.

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

В командной оболочке именованный канал создается с помощью команды «mkfifo»:

mkfifo <namedpipe>

где «namedpipe» – имя создаваемого именованного канала. Например, после ввода команды

mkfifo fifofile

в текущем рабочем каталоге появится файл с именем «fifofile».

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

echo “It’s data 1” > fifofile &

echo “It’s data 2” > fifofile &

cat fifofile

Результат ввода команд и получаемого вывода представлена на Рисунке Рисунок 6.

Рисунок 6. Пример работы с именованным каналом.

Команды «echo» запускаются в фоновом режиме и находятся в состоянии «S» до тех пор, пока не будет вызвана команда «cat …». При вызове «cat …» именованный канал fifofile открывается на чтение, команды «echo …» переходят в состояние «R» и записывают данные в fifofile. Эти данные считываются cat и выводятся на экран терминала, после чего фоновые команды «echo» завершаются.

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

Соседние файлы в папке OS_labs