Билет. Взаимодействие процессов по модели «главный-подчиненный».
Обзор форм межпроцессного взаимодействия в UNIX был бы не полон, если бы мы не рассмотрели простейшую форму взаимодействия, используемую для отладки — трассировку процессов. Принципиальное отличие трассировки от остальных видов межпроцессного взаимодействия в том, что она реализует модель «главный-подчиненный»: один процесс получает возможность управлять ходом выполнения, а также данными и кодом другого.
В UNIX трассировка возможна только между родственными процессами: процесс-родитель может вести трассировку только непосредственно порожденных им потомков, при этом трассировка начинается только после того, как процесс-потомок дает разрешение на это.
Далее схема взаимодействия процессов путем трассировки такова: выполнение отлаживаемого процесса-потомка приостанавливается всякий раз при получении им какого-либо сигнала, а также при выполнении вызова exec(). Если в это время отлаживающий процесс осуществляет системный вызов wait(), этот вызов немедленно возвращает управление. В то время, как трассируемый процесс находится в приостановленном состоянии, процесс-отладчик имеет возможность анализировать и изменять данные в адресном пространстве отлаживаемого процесса и в пользовательской составляющей его контекста. Далее, процесс-отладчик возобновляет выполнение трассируемого процесса до следующего приостановка (либо, при пошаговом выполнении, для выполнения одной инструкции).
Основной системный вызов, используемый при трассировке,– это ptrace(), прототип которого выглядит следующим образом:
#include <sys/ptrace.h>
int ptrace(int cmd, pid, addr, data)
где cmd – код выполняемойкоманды,pid –идентификатор процесса-потомка, addr – некоторый адрес в адресном пространстве процесса-потомка, data – слово информации.
Чтобы оценить уровень предоставляемых возможностей, рассмотрим основные коды - cmd операций этой функции.
Билет.Система межпроцессного взаимодействия IPC. Общие концепции
Для всех средств IPC приняты общие правила именования объектов, позволяющие процессу получить доступ к такому объекту. Для именования объекта IPC используется ключ, представляющий собой целое число. Ключи являются уникальными во всей UNIX-системе идентификаторами объектов IPC, и зная ключ для некоторого объекта, процесс может получить к нему доступ. При этом процессу возвращается дескриптор объекта, который в дальнейшем используется для всех операций с ним.
Общие принципы работы с разделяемыми ресурсами.
Общим для всех ресурсов является механизм именования. Кроме того, для каждого IPC-ресурса поддерживается идентификатор его владельца и структура, описывающая права доступа к нему. Подобно файлам, права доступа задаются отдельно для владельца, его группы и всех остальных пользователей; однако, в отличие от файлов, для разделяемых ресурсов поддерживается только две категории доступа: по чтению и записи. Для создания разделяемого ресурса с заданным ключом, либо подключения к уже существующему ресурсу с таким ключом используются ряд системных вызовов, имеющих общий суффикс get.
IPC: очередь сообщений.
Очередь сообщений представляет собой некое хранилище типизированных сообщений, организованное по принципу FIFO. Любой процесс может помещать новые сообщения в очередь и извлекать из очереди имеющиеся там сообщения. Каждое сообщение имеет тип, представляющий собой некоторое целое число. Благодаря наличию типов сообщений, очередь можно интерпретировать двояко — рассматривать ее либо как сквозную очередь неразличимых по типу сообщений, либо как некоторое объединение подочередей, каждая из которых содержит элементы определенного типа. Извлечение сообщений из очереди происходит согласно принципу FIFO – в порядке их записи, однако процесс-получатель может указать, из какой подочереди он хочет извлечь сообщение, или, иначе говоря, сообщение какого типа он желает получить – в этом случае из очереди будет извлечено самое «старое» сообщение нужного типа.
Рассмотрим набор системных вызовов, поддерживающий работу с очередями сообщений.
Доступ к очереди сообщений.
Для создания новой или для доступа к существующей используется системный вызов:
Int msgget (key_t key, int msgflag)
Отправка сообщения.
Для отправки сообщения используется функция msgsnd():
int msgsnd (int msqid, const void *msgp, size_t msgsz, int msgflg)
Получение сообщения.
Для получения сообщения имеется функция msgrcv:
int msgrcv (int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)