Понятие о pipe. Системный вызов pipe()


Наиболее простым способом для передачи информации с помощью потоковой модели между различными процессами или даже внутри одно­го процесса в операционной системе UNIX является pipe (канал, труба, конвейер).

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

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

Понятно, что если бы все достоинство pip'oB сводилось к замене функции копирования из памяти в память внутри одного процесса на пе­ресылку информации через операционную систему, то овчинка не стоила бы выделки. Однако таблица открытых файлов наследуется процессом-ребенком при порождении нового процесса системным вызовом fork () и входит в состав неизменяемой части системного контекста процесса при системном вызове ехес () (за исключением тех потоков данных, для файловых дескрипторов которых был специальными средствами выстав­лен признак, побуждающий операционную систему закрыть их при вы­полнении ехес (), однако их рассмотрение выходит за рамки нашего курса). Это обстоятельство позволяет организовать передачу информации через pipe между родственными процессами, имеющими общего праро­дителя, создавшего pipe.

двунаправленной связи между родственными процессами через pipe

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

Более простой способ ор­ганизации двунаправленной связи между родственными процессами заклю­чается в использовании двух pipe

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

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

 

Разделяемая память

Для создания области разделяемой памяти с определенным ключом или доступа по ключу к уже существующей области применяется системный вызов shmget (). Существует два варианта его использования для созда­ния новой области разделяемой памяти:

Стандартный способ. В качестве значения ключа системному вызо­ву поставляется значение, сформированное функцией ftok() для некоторого имени файла

Нестандартный способ. В качестве значения ключа указывается спе­циальное значение IPC_PRIVATE.

Доступ к созданной области разделяемой памяти в дальнейшем обеспечивается ее дескриптором, который вернет системный вызов shmget (). Доступ к уже существующей области также может осуществ­ляться двумя способами:

• Если мы знаем ее ключ, то, используя вызов shmget ( ), можем по­лучить ее дескриптор.

• Либо мы можем воспользоваться тем, что дескриптор System V IPC действителен в рамках всей операционной системы, и передать его значение от процесса, создавшего разделяемую память, текущему процессу. Отметим, что при создании разделяемой памяти с помо­щью значения ipc_private — это единственно возможный способ.

• После получения дескриптора необходимо включить область разде­ляемой памяти в адресное пространство текущего процесса. Это осущест­вляется с помощью системного вызова shmat (). При нормальном завер­шении он вернет адрес разделяемой памяти в адресном пространстве те­кущего процесса. Дальнейший доступ к этой памяти осуществляется с по­мощью обычных средств языка программирования.

• После окончания использования разделяемой памяти процесс может уменьшить размер своего адресного пространства, исключив из него эту область с помощью системного вызова shmdt (). Отметим, что в качестве параметра системный вызов shmdt () требует адрес начала области разде­ляемой памяти в адресном пространстве процесса, т. е. значение, которое вернул системный вызов shmat (), поэтому данное значение следует со­хранять на протяжении всего времени использования разделяемой памяти.

Сигналы

Сигналы — одно из традиционных средств межпроцессного взаимодействия в UNIX. Сигнал может быть отправлен процессу операционной системой или другим процессом. Операционная система использует сигналы для доставки процессу уведомлений об ошибках и неправильном поведении.

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

У сигнала есть только одна характеристика, несущая информацию — его номер (целое число). Иначе говоря, сигналы — это заранее определённый и пронумерованный список сообщений. Для удобства использования каждый сигнал имеет сокращённое буквенное имя. Список сигналов и их имён стандартизован и практически не отличается в различных версиях UNIX. Для отправки сигналов процессам используется специальный системный вызов kill и одноимённая ему пользовательская утилита. Стандарт POSIX определяет 28 сигналов, вот несколько примеров:

§ SIGINT (2) — Сигнал передается активному приложению при нажатии сочетания Ctrl+C, по умолчанию завершает процесс.

§ SIGKILL (9) — Сигнал аварийного завершения процесса. По этому сигналу процесс завершается немедленно — без освобождения ресурсов. Этот сигнал не может быть перехвачен, заблокирован или переопределён самим процессом, всегда используется стандартный обработчик опрационной системы. Этот сигнал используется для гарантированного завершения процесса.

§ SIGTERM (15) — Сигнал завершения процесса, как правило используется для корректного завершения его работы.

§ SIGUSR1 (10) и SIGUSR2 (12) — Зарезервированные сигналы под нужды программистов.

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

Каналы

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


По умолчанию в UNIX каждому процессу при запуске ставится в соответствие три открытых файла: стандартного ввода, стандартного вывода и стандартного вывода для ошибок. С помощью средств командной строки такие потоки для разных процессов могут быть объединены так, что, к примеру, вывод одного процесса будет подаваться на ввод другого. То есть процесс работает с тремя потоками данных одинаково вне зависимости от того, обычные это файлы или же кананлы. В более общем смысле такие потоки называют неименованными каналами. Канал создаётся по запросу и существует только в ходе работы двух процессов, другие процессы в системе не могут обратиться к этому каналу. Если процесс на одной из сторон канала завершается и закрывает канал, другому процессу посылается специальный сигнал — SIGPIPE.

Другой вид каналов в UNIX — именованные каналы — представляют собой особый тип файлов. Эти файлы располагаются в файловой системе и могут быть открыты любым процессом. Одни процессы записывают данные в канал, другие — читают из него, данные продвигаются по каналу в порядке очереди (FIFO).

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

Вызов POSIX — pipe().

Разделяемая память


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

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

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

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

Вызовы POSIX — shmem(), mmap().

Семафоры

Одним из первых механизмов, предложенных для синхронизации поведения процессов, стали семафоры, концепцию которых описал Дейкстра (Dijkstra) в 1965 году.

Дейкстра предложил две операции, down и up. Операция down сравнивает значение семафора с нулем. Если значение семафора больше нуля, операция down уменьшает его и просто возвращает управление. Если значение семафора равно нулю, процедура down не возвращает управление процессу, а процесс переводится в состояние ожидания. Все операции проверки значения семафора, его изменения и перевода процесса в состояние ожидания выполняются как единое и неделимое элементарное действие. Тем самым гарантируется, что после начала операции ни один процесс не получит доступа к семафору до окончания или блокирования операции. Атомарность операции чрезвычайно важна для разрешения проблемы синхронизации и предотвращения состояния состязания.

Операция up увеличивает значение семафора. Если с этим семафором связаны один или несколько ожидающих процессов, которые не могут завершить более раннюю операцию down, один из них выбирается системой (например, случайным образом) и ему разрешается завершить свою операцию down. Таким образом, после операции up, примененной к семафору, связанному с несколькими ожидающими процессами, значение семафора так и останется равным 0, но число ожидающих процессов уменьшится на единицу. Операция увеличения значения семафора и активизации процесса тоже неделима. Ни один процесс не может быть блокирован во время выполнения операции up, как ни один процесс не мог быть блокирован во время выполнения операции wakeup в предыдущей модели.

Сокеты (sockets)

Это очень важная технология, т.к. именно она отвечает за обмен данными в Интернет. Сокеты также часто используются в крупных ЛВС. Взаимодействие происходит через т.н. разъемы-"сокеты", которые представляют собой абстракцию конечных точек коммуникационной линии, соединяющей два приложения. С этими объектами программа и должна работать, например, ждать соединения, посылать данные и т.д. В Windows входит достаточно мощный API для работы с сокетами.



Дата добавления: 2017-06-13; просмотров: 3938;


Поиск по сайту:

Воспользовавшись поиском можно найти нужную информацию на сайте.

Поделитесь с друзьями:

Считаете данную информацию полезной, тогда расскажите друзьям в соц. сетях.
Poznayka.org - Познайка.Орг - 2016-2024 год. Материал предоставляется для ознакомительных и учебных целей.
Генерация страницы за: 0.017 сек.