Составители:
Рубрика:
6.2.2. Асинхронные вызовы процедур
Для реализации асинхронного ввода-вывода в операционной систе-
ме предусмотрен специальный механизм, основанный на так называемых
асинхронных вызовах процедур (Аsynchronous Procedure Call, APC). Это один
из базовых механизмов, необходимый для нормального функционирова-
ния операционной системы.
Практика показала, что такой механизм был бы эффективен и для ре-
ализации самих приложений. Более того, для реализации асинхронного
ввода-вывода с поддержкой функции завершения система уже обязана
была предоставить этот механизм. Для реализации этого механизма опе-
рационная система ведет списки процедур, которые она должна вызывать
в контексте данного потока, с тем ограничением, что прерывать работу за-
нятого потока в произвольный момент времени система не должна. Поэ-
тому для обслуживания накопившихся в очереди процедур необходимо
перевести поток в специальное состояние ожидания оповещения (alertable
waiting)– для этого Win32 API предусматривает специальный набор функ-
ций: например, SleepEx, WaitForSingleObjectEx и др.
Здесь и во многих примерах далее, чтобы не загромождать код приме-
ра, опущена проверка ошибок:
VOID CALLBACK ApcProc( ULONG_PTR dwData )
{
/* ... */
}
int main( void )
{
QueueUserAPC( ApcProc, GetCurrentThread(), 0 );
/* ... */
SleepEx( 1000, TRUE );
return 0;
}
Обычно APC используются самой системой для реализации асин-
хронного ввода-вывода и некоторых других операций, но разработчикам
также предоставлена функция QueueUserAPC, с помощью которой можно
ставить в APC очередь запросы для вызова собственных функций.
6.2.3. Процессы, потоки и объекты ядра
Обсуждение реализации мультипрограммирования в операционной
системе неизбежно приводит к обсуждению вопросов безопасности.
В мультипрограммной среде может одновременно выполняться значи-
тельное количество процессов, представляющих разных пользователей, и
Основы многозадачности
207
выполнить некоторые специальные действия. Процедура завер-
шения обязательно вызывается в контексте того потока, кото-
рый вызвал операцию ввода-вывода, – а для этого необходимо,
чтобы поток был приостановлен, так как операционная система
не должна прерывать работу активного потока. Следует переве-
сти поток в состояние ожидания оповещения (alertable waiting) –
при этом он не выполняется и может быть прерван для обработ-
ки процедуры завершения:
ov.Offset = 12345;
if ( WriteFileEx( fh, buffer, sizeof(buffer), &ov, io_done ) ) {
/* пока операция ввода-вывода выполняется, выполняем некоторые
операции и переходим в режим ожидания оповещения,
например, так: */
if ( SleepEx( INFINITE, TRUE ) != WAIT_IO_COMPLETION ) {
/* ввод-вывод пока не завершен, возможно, ошибка */
}
} else {
/* возникла ошибка */
}
/* нам еще надо предоставить собственную процедуру
завершения ввода-вывода. В простейшем варианте
она может ничего не делать: */
VOID CALLBACK io_done(
DWORD dwErr, DWORD dwWritten, LPOVERLAPPED lpOv
) {
...
}
Этот подход наиболее трудоемок и наименее распространен; на
практике самым эффективным является механизм выполнения
асинхронных операций с ожиданием на объектах ядра. Однако
механизм вызова функций завершения (расширенный возмож-
ностью автоматического выбора потока, осуществляющего об-
работку функции завершения) послужил основой для реализа-
ции одного из очень эффективных механизмов взаимодействия
потоков – порта завершения ввода-вывода.
При использовании асинхронного ввода-вывода необходимо очень
внимательно следить за выделением и освобождением ресурсов – особен-
но памяти, занятой структурами OVERLAPPED, и буферами, участвующими в
операциях ввода-вывода.
Асинхронный ввод-вывод является примером мультипроцессирова-
ния с использованием функционально различных устройств.
206
CIL и системное программирование в Microsoft .NET
206 CIL и системное программирование в Microsoft .NET Основы многозадачности 207 выполнить некоторые специальные действия. Процедура завер- 6.2.2. Асинхронные вызовы процедур шения обязательно вызывается в контексте того потока, кото- рый вызвал операцию ввода-вывода, – а для этого необходимо, Для реализации асинхронного ввода-вывода в операционной систе- чтобы поток был приостановлен, так как операционная система ме предусмотрен специальный механизм, основанный на так называемых не должна прерывать работу активного потока. Следует переве- асинхронных вызовах процедур (Аsynchronous Procedure Call, APC). Это один сти поток в состояние ожидания оповещения (alertable waiting) – из базовых механизмов, необходимый для нормального функционирова- при этом он не выполняется и может быть прерван для обработ- ния операционной системы. ки процедуры завершения: Практика показала, что такой механизм был бы эффективен и для ре- ализации самих приложений. Более того, для реализации асинхронного ov.Offset = 12345; ввода-вывода с поддержкой функции завершения система уже обязана if ( WriteFileEx( fh, buffer, sizeof(buffer), &ov, io_done ) ) { была предоставить этот механизм. Для реализации этого механизма опе- /* пока операция ввода-вывода выполняется, выполняем некоторые рационная система ведет списки процедур, которые она должна вызывать операции и переходим в режим ожидания оповещения, в контексте данного потока, с тем ограничением, что прерывать работу за- например, так: */ нятого потока в произвольный момент времени система не должна. Поэ- if ( SleepEx( INFINITE, TRUE ) != WAIT_IO_COMPLETION ) { тому для обслуживания накопившихся в очереди процедур необходимо /* ввод-вывод пока не завершен, возможно, ошибка */ перевести поток в специальное состояние ожидания оповещения (alertable } waiting) – для этого Win32 API предусматривает специальный набор функ- } else { ций: например, SleepEx, WaitForSingleObjectEx и др. /* возникла ошибка */ Здесь и во многих примерах далее, чтобы не загромождать код приме- } ра, опущена проверка ошибок: /* нам еще надо предоставить собственную процедуру завершения ввода-вывода. В простейшем варианте VOID CALLBACK ApcProc( ULONG_PTR dwData ) она может ничего не делать: */ { VOID CALLBACK io_done( /* ... */ DWORD dwErr, DWORD dwWritten, LPOVERLAPPED lpOv } ) { int main( void ) ... { } QueueUserAPC( ApcProc, GetCurrentThread(), 0 ); Этот подход наиболее трудоемок и наименее распространен; на /* ... */ практике самым эффективным является механизм выполнения SleepEx( 1000, TRUE ); асинхронных операций с ожиданием на объектах ядра. Однако return 0; механизм вызова функций завершения (расширенный возмож- } ностью автоматического выбора потока, осуществляющего об- Обычно APC используются самой системой для реализации асин- работку функции завершения) послужил основой для реализа- хронного ввода-вывода и некоторых других операций, но разработчикам ции одного из очень эффективных механизмов взаимодействия также предоставлена функция QueueUserAPC, с помощью которой можно потоков – порта завершения ввода-вывода. ставить в APC очередь запросы для вызова собственных функций. При использовании асинхронного ввода-вывода необходимо очень внимательно следить за выделением и освобождением ресурсов – особен- 6.2.3. Процессы, потоки и объекты ядра но памяти, занятой структурами OVERLAPPED, и буферами, участвующими в Обсуждение реализации мультипрограммирования в операционной операциях ввода-вывода. системе неизбежно приводит к обсуждению вопросов безопасности. Асинхронный ввод-вывод является примером мультипроцессирова- В мультипрограммной среде может одновременно выполняться значи- ния с использованием функционально различных устройств. тельное количество процессов, представляющих разных пользователей, и
Страницы
- « первая
- ‹ предыдущая
- …
- 108
- 109
- 110
- 111
- 112
- …
- следующая ›
- последняя »