- •Экзаменационный билет № 1
- •Состояния потоков
- •Экзаменационный билет № 2
- •Экзаменационный билет № 3
- •Указатели файлов
- •Определение размера файла
- •Экзаменационный билет № 4
- •Экзаменационный билет № 5
- •Экзаменационный билет № 6
- •Экзаменационный билет № 7
- •Экзаменационный билет № 8
- •Экзаменационный билет № 9
- •Экзаменационный билет № 10
- •Экзаменационный билет № 11
- •Динамически компонуемые библиотеки
- •Статические и динамические библиотеки
- •Неявное связывание
- •Экзаменационный билет № 12
- •Мьютексы
- •Покинутые мьютексы
- •Экзаменационный билет № 13
- •Отображение файлов
- •Экзаменационный билет № 14
- •Стратегии обработки файлов
- •Экзаменационный билет № 15
- •Экзаменационный билет № 16
- •Экзаменационный билет № 17
- •Ожидание завершения потока
- •Экзаменационный билет № 18
- •Обзор потоков
- •Основные сведения о потоках
- •Семафоры
- •Экзаменационный билет № 19
- •Исключения и обработчики исключений
- •Экзаменационный билет № 20
- •Совместное использование объектов ядра приложениями и службами
- •Экзаменационный билет № 21
- •Экзаменационный билет № 22
- •Экзаменационный билет № 23
- •Блоки и строки окружения
- •Необходимость в синхронизации потоков
- •Экзаменационный билет № 24
- •Экзаменационный билет № 25
Совместное использование объектов ядра приложениями и службами
Возможны ситуации, в которых служба и приложения разделяют объект ядра. Например, служба может использовать именованный мьютекс для защиты разделяемой области памяти, используемой для обмена данными с приложениями. Более того, в нашем примере также будет применяться разделяемый объект ядра, которым в данном случае является отображение файла.
Существует одна трудность, связанная с тем, что контекст безопасности приложений отличается от контекста безопасности служб, выполняющихся от имени системной учетной записи. Даже если защита не требуется, было бы нелогично создавать и (или) открывать разделяемые объекты ядра с указателем атрибутов безопасности, установленным в NULL (см. глава 15). Вместо этого необходим, по крайней мере, нулевой список разграничительного контроля доступа (см. главу 15), то есть приложения и служба должны использовать ненулевую структуру атрибутов защиты. В общем случае вы захотите защитить объекты, и этот вопрос также будет рассмотрен в главе 15.
Следует обратить ваше внимание также на то, что если служба выполняется от имени системной учетной записи, то могут возникать трудности с доступом службы к таким ресурсам, как разделяемые файлы, находящиеся на других машинах.
3. Обработчики завершения.
Обработчик завершения служит почти для той же цели, что и обработчик
исключения, но он выполняется, когда поток выходит из блока как при
нормальном ходе программы, так и при наступлении исключения. Кроме того,
обработчик завершения не может выявить исключение.
Обработчик завершения создается с помощью ключевого слова __finally в
операторе try-finally. Его структура такая же, как и у оператора try-except,
однако здесь нет выражения фильтра. Обработчики завершения, подобно
обработчикам исключений, дают удобный способ закрытия дескрипторов,
освобождения ресурсов, восстановления масок и других действий по
возвращению процесса в определенное состояние перед выходом из блока.
Например, программа может выполнять операторы return в середине блока, а обработчик завершения будет выполнять работу по очистке. Таким образом, не требуется ни вставлять код очистки непосредственно в блок, ни прибегать к оператору goto, чтобы перейти к этому коду.
__try { /* Блок кода. */ }
__finally { /* Обработчик завершения (блок finally). */ }
Выход из блока Try
Обработчик завершения выполняется всякий раз, когда управление выходит
из блока try по любой из следующих причин:
• достигается конец блока try и управление "проваливается" в обработчик
завершения;
• выполняется один из следующих операторов, которые вызывают выход из
блока: return, break, goto, longjmp, continue, __leave
• исключение.
Аварийное завершение
Завершение по любой другой причине, отличной от достижения конца блока
и перехода к обработчику завершения или выполнения оператора __leave,
считается аварийным. Оператор __leave выполняет переход к концу блока
__try и вызов обработчика завершения, что более эффективно, чем goto, так
как в этом случае не требуется разворачивать стек. В обработчике завершения
можно применять следующую функцию, чтобы определить, как завершился
блок try:
BOOL AbnormalTermination (VOID)
Функция возвращает TRUE при аварийном завершении и FALSE при
нормальном завершении.
Выполнение обработчика завершения и выход из него
Обработчик завершения, или блок finally, выполняется в контексте блока
или функции, которую он контролирует. Управление может передаваться с
конца обработчика завершения на следующий оператор. Также в обработчике
завершения может выполняться оператор перехода (return, break, continue,
goto, longjmp или __leave). Еще один вариант — выход из обработчика по
исключению.
Сочетание блоков Finally и Except
Отдельный блок try должен иметь один блок finally или except; оба блока
сразу не допускаются. Но можно вложить один блок в другой; часто этот метод
оказывается полезным. Следующий код правилен и гарантирует, что
временный файл будет удален при выходе из цикла как по логике программы,
так и по исключению. Эта методика также полезна для того, чтобы
гарантировать разблокирование файла. Можно также применить внутренний
блок try-except для операций с плавающей запятой.
try { /* Внешний блок try-except. */
while (...) try ( /* Внутренний блок try-finally. */
hFile = CreateFile (TempFile, ...);
if (...) try { /* Внутренний блок try-except. */
/* Разрешение исключений ПЗ и выполнение вычислений.
*/
}
except (EXCEPTION EXECUTE HANDLER) {
... /* Обработка исключения ПЗ. */ _clearfp (); }
... /* Обработка, не связанная с ПЗ. */ }
finally { /* Конец цикла while loop. */
/* Выполняется на каждой итерации цикла */
CloseHandle (hFile); DeleteFile (TempFile); } }
except (выражение_фильтра) {
/* Обработчик исключения. */ }
Обработчики завершения служат в основном тем же целям, что и обработчики исключений, но выполняются, когда поток покидает блок в результате нормального выполнения программы, а также когда возникает исключение. С другой стороны, обработчик завершения не может распознавать исключения.
Обработчик завершения строится с использования ключевого слова __finally в операторе try…finally. Структура этого оператора аналогична структуре оператора try…finally, но в ней отсутствует выражение фильтра. Как и обработчики исключений, обработчики завершения предоставляют удобные возможности для закрытия дескрипторов, освобождения ресурсов, восстановления масок и выполнения иных действий, направленных на восстановление известного состояния системы после выхода из блока. Например, программа может выполнять операторы return внутри блока, оставляя всю работу по "уборке мусора" обработчику завершения. Благодаря этому отпадает необходимость во включении кода очистки в код самого блока или переходе к коду очистки при помощи оператора goto.
