Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform
Шрифт:
Данные рассуждения применимы не только к составным сообщениям, но и ко всем сообщениям, принимаемым библиотекой администратора ресурсов. Первое, что делает библиотека администратора ресурсов, — она блокирует атрибутную запись, соответствующую ресурсу, используемому полученным сообщением. Затем она обрабатывает одно или более «подсообщений», содержащихся в полученном сообщении. Затем она снова разблокирует атрибутную запись.
Это гарантирует, что поступающие сообщения обрабатываются атомарно, поскольку никакой другой поток администратора ресурсов (в случае многопоточного администратора, конечно) не может «влезть» и изменить ресурс, пока наш поток этот ресурс использует. Без блокировок два клиентских потока могли бы оба выдать то, что, по их мнению, являлось бы атомарным составным сообщением (скажем,
Блокировка и разблокировка ресурса выполняются вспомогательными функциями по умолчанию (iofunc_lock_ocb_default и iofunc_unlock_ocb_default), которые размещаются в таблице функций ввода/вывода в полях lock_ocb и unlock_ocb соответственно. Вы можете, конечно, переназначить эти функции, если хотите выполнить в процессе блокировки и разблокировки какие-либо дополнительные действия.
Заметьте, что ресурс разблокируется перед вызовом io_close. Это необходимо, поскольку функция io_close освободит OCB, что автоматически сделает недействительным указатель на атрибутную запись, а блокировка хранится именно там!
Замечания о функциях установления соединения
Перед тем как углубиться в отдельные сообщения, однако, есть смысл подчеркнуть, что для всех функции установления соединения структура сообщений идентична (взято из
Вы заметите, что я разделил структуру
Первая часть состоит из полей, которые библиотека администратора ресурсов использует для:
• определения типа сообщения, полученного от клиента;
• проверки сообщения на достоверность (не является ли оно дезинформацией);
• отслеживания режима доступа (используется вспомогательными функциями).
Для
простоты я бы рекомендовал вам всегда применять вспомогательные функции (из семейства iofunc_*_default) во всех функциях установления соединения. Эти функции возвратят вам признак успешного/неудачного завершения, после чего вы сможете использовать в функции установления соединения «поля для конечного пользователя».Вторая половина полей непосредственно относится к вашей реализации функции установления соединения:
path_len и path
Имя пути (и его длина), которые являются операндом (то есть это имя пути, над которым производится действие).
extra_type и extra_len
Дополнительные параметры (имена путей, например), соответствующее данной функции установления соединения.
Чтобы получить представление о том, как поле path используется в качестве «имени пути, над которым производится действие», давайте рассмотрим что-нибудь типа функции rename. Эта функция принимает два имени пути: «изначальное» имя пути и «новое» имя пути. Изначальное имя пути передается в path, потому что именно над ним производится операция (это имя файла, подлежащего переименованию). Новое имя пути — аргумент данной операции. Вы увидите, что параметр extra, который передается функции установления соединения, как раз содержит указатель на аргумент операции, в данном случае — на новое имя пути.
(В принятой реализации новое имя пути располагается в памяти непосредственно следом за изначальным (на которое указывает path) с учетом выравнивания, но вам делать на этот счет ничего не надо — параметр extra уже содержит правильный указатель.)
Алфавитный список функций установления соединения и ввода/вывода
В данном разделе в алфавитном порядке приведен список точек входа в функции установления соединения и ввода/вывода, которые вы можете заполнять самостоятельно (эти две таблицы затем передаются функции pathname_attach). Помните, что если вы просто вызываете функцию iofunc_func_init, все эти точки входа будут заполнены соответствующими значениями по умолчанию; вам следует переопределять конкретные точки входа только в том случае, если вы собираетесь обрабатывать данное конкретное сообщение самостоятельно. Ниже, в разделе «Примеры», вы увидите несколько примеров общеупотребительных функций.
Чтобы не путать точки входа в функции-обработчики сообщений с вызовами клиентской Си-библиотеки (например, open), к именам всех приведенных здесь функций добавлен префикс «io_». Например, обработчик функции установления соединения open будет называться io_open.