15.7. Передача дескрипторов

15.7. Передача дескрипторов

Когда нам требуется передать дескриптор от одного процесса другому, обычно мы выбираем одно из двух решений:

1. Дочерний процесс использует все открытые дескрипторы совместно с родительским процессом после вызова функции fork.

2. Все дескрипторы обычно остаются открытыми при вызове функции exec.

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

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

ПРИМЕЧАНИЕ

Передача ядром 4.4BSD открытого дескриптора через доменный сокет Unix описывается в главе 18 [112].

SVR4 использует другую технологию внутри ядра для передачи открытого дескриптора: команды I_SENDFD и I_RECVFD функции ioctl, описанные в разделе 15.5.1 [110]. Но процесс все же имеет возможность доступа к указанному свойству ядра за счет доменного сокета Unix. В этой книге мы описываем применение доменных сокетов Unix для передачи открытых дескрипторов, поскольку это наиболее переносимая технология программирования: она работает как с Беркли-ядрами, так и с SVR4, в то время как команды I_SENDFD и I_RECVFD функции ioctl работают только в SVR4.

Технология 4.4BSD позволяет передавать множество дескрипторов с помощью одиночной функции sendmsg, в то время как технология SVR4 передает за один раз только один дескриптор. Во всех наших примерах за один раз передается один дескриптор.

Шаги при передаче дескриптора между процессами будут такими:

1. Создание доменного сокета Unix, или потокового сокета, или дейтаграммного сокета.

Если целью является породить с помощью функции fork дочерний процесс, с тем чтобы дочерний процесс открыл дескриптор и передал его обратно родительскому процессу, родительский процесс может вызвать функцию socketpair для создания потокового канала, который может использоваться для передачи дескриптора.

Если процессы не являются родственными, сервер должен создать потоковый доменный сокет Unix, связать его при помощи функции bind с полным именем, тем самым позволяя клиенту соединиться с этим сокетом при помощи функции connect. Затем клиент может отправить запрос серверу для открытия некоторого дескриптора, а сервер может передать дескриптор обратно через доменный сокет Unix. Как альтернатива между клиентом и сервером может также использоваться дейтаграммный доменный сокет Unix, однако преимущества этого способа невелики, к тому же существует возможность игнорирования дейтаграммы. Далее в примерах этой главы мы будем использовать потоковый сокет между клиентом и сервером.

2. Один процесс открывает дескриптор при помощи вызова любой из функций Unix, возвращающей дескриптор, например open, piре, mkfifo, socket или accept. От одного процесса к другому можно передать дескриптор любого типа, поэтому мы называем эту технологию «передачей дескриптора», а не «передачей дескриптора файла».

3. Отправляющий процесс строит структуру msghdr (см. раздел 14.5), содержащую дескриптор, который нужно передать. В POSIX определено, что дескриптор должен отправляться как вспомогательные данные (элемент msg_control структуры msghdr, см. раздел 14.6), но более старые реализации используют элемент msg_accrights. Отправляющий процесс вызывает функцию sendmsg для отправки дескриптора через доменный сокет Unix, созданный на шаге 1. На этом этапе мы говорим, что дескриптор находится «в полете». Даже если отправляющий процесс закроет дескриптор после вызова функции sendmsg, но до вызова принимающим процессом функции recvmsg, дескриптор останется открытым для принимающего процесса. Отправка дескриптора увеличивает счетчик ссылок дескриптора на единицу.

4. Принимающий процесс вызывает функцию recvmsg для получения дескриптора через доменный сокет Unix, созданный на шаге 1. Номер дескриптора в принимающем процессе может отличаться от номера дескриптора в отправляющем процессе. Передача дескриптора — это не передача номера дескриптора. Этот процесс включает создание нового дескриптора в принимающем процессе, который ссылается на ту же запись таблицы файлов в ядре, что и дескриптор, отправленный отправляющим процессом.

Клиент и сервер должны располагать некоторым протоколом уровня приложения, с тем чтобы получатель дескриптора имел информацию о времени его появления. Если получатель вызывает функцию recvmsg, не выделив места в памяти для получения дескриптора, и дескриптор передается как готовый для чтения, то передаваемый дескриптор закрывается [128, с. 518]. Кроме того, нужно избегать установки флага MSG_PEEK в функции recvmsg, если предполагается получение дескриптора, поскольку в этом случае результат непредсказуем.

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

Передача пакетов

Из книги Skype: бесплатные звонки через Интернет. Начали! автора Гольцман Виктор Иосифович

Передача пакетов Следующий этап – это передача пакетов. Транспортировка цифрового трафика осуществляется через Интернет с помощью технологии TCP/IP. Термин TCP/IP обозначает целый набор технологий и прикладных программ, связанных с передачей данных через Интернет. Сюда


Правило 28: Избегайте возвращения «дескрипторов» внутренних данных

Из книги Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ автора Мейерс Скотт

Правило 28: Избегайте возвращения «дескрипторов» внутренних данных Представим, что вы работаете над приложением, имеющим дело с прямоугольниками. Каждый прямоугольник может быть представлен своим левым верхним углом и правым нижним. Чтобы объект Rectangle оставался


Счетчики дескрипторов процессов

Из книги Системное программирование в среде Windows автора Харт Джонсон М

Счетчики дескрипторов процессов Распространенной ошибкой программистов является пренебрежение закрытием дескрипторов после того, как необходимость в них отпала; это может стать причиной утечки ресурсов, что, в свою очередь, может приводить к снижению


Дублирование дескрипторов

Из книги Разработка приложений в среде Linux. Второе издание автора Джонсон Майкл К.

Дублирование дескрипторов Родительскому и дочернему процессам может требоваться различный доступ к объекту, идентифицируемому дескриптором, который наследует дочерний процесс. Кроме того, процессу вместо псевдодескриптора, получаемого с помощью функции GetModuleFileName или


Чтение и изменение дескрипторов безопасности

Из книги Язык программирования Си для персонального компьютера автора Бочков C. О.

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


11.5.3. Дублирование файловых дескрипторов

Из книги 1С: Бухгалтерия 8 с нуля. 100 уроков для начинающих автора Гладкий Алексей Анатольевич

11.5.3. Дублирование файловых дескрипторов Иногда процессам требуется создать новый файловый дескриптор, который ссылается на ранее открытый файл. Командные оболочки используют эту функциональность для перенаправления стандартного ввода, вывода и потока ошибок по


22.3.7. Закрытие файловых дескрипторов

Из книги Мир InterBase. Архитектура, администрирование и разработка приложений баз данных в InterBase/FireBird/Yaffil автора Ковязин Алексей Николаевич

22.3.7. Закрытие файловых дескрипторов В системах Linux и Unix файловые дескрипторы, как правило, наследуются через системные вызовы exec() (и всегда наследуются через fork() и vfork()). В большинстве случаев такое поведение нежелательно, поскольку только разделяться должны только stdin,


9.6.2.2. Переопределение дескрипторов (handle)

Из книги Linux и UNIX: программирование в shell. Руководство разработчика. автора Тейнсли Дэвид

9.6.2.2. Переопределение дескрипторов (handle) Когда программа начинает выполняться, пять дескрипторов (handle), соответствующих стандартным вводу, выводу, выводу сообщений об ошибках, порту и устройству печати, уже назначены. Пользователь может использовать значения этих


Урок № 67. Передача собственных материалов в переработку на сторону и передача продукции из давальческого сырья

Из книги UNIX: разработка сетевых приложений автора Стивенс Уильям Ричард

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


9.1.1.2. Разделение дескрипторов файлов

Из книги автора

9.1.1.2. Разделение дескрипторов файлов Атрибуты, которые порожденный процесс наследует от родителя, устанавливаются в те же значения, которые были в родительском процессе в момент выполнения fork(). Однако, с этого момента два процесса продолжают идти собственными путями


9.1.1.3. Разделение дескрипторов файлов и close()

Из книги автора

9.1.1.3. Разделение дескрипторов файлов и close() Тот факт, что несколько дескрипторов файлов могут указывать на один и тот же открытый файл, имеет важное следствие: файл не закрывается до тех пор, пока не будут закрыты все дескрипторы файла.Позже в главе мы увидим, что несколько


Максимальное число дескрипторов для функции select

Из книги автора

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


15.7. Передача дескрипторов

Из книги автора

15.7. Передача дескрипторов Когда нам требуется передать дескриптор от одного процесса другому, обычно мы выбираем одно из двух решений:1. Дочерний процесс использует все открытые дескрипторы совместно с родительским процессом после вызова функции fork.2. Все дескрипторы