Джонсон Харт - Системное программирование в среде Windows
- Название:Системное программирование в среде Windows
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2005
- Город:Москва • Санкт-Петербург • Киев
- ISBN:5-8459-0879-5
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Джонсон Харт - Системное программирование в среде Windows краткое содержание
Эта книга посвящена вопросам разработки приложений с использованием интерфейса прикладного программирования операционных систем компании Microsoft (Windows 9х, Windows XP, Windows 2000 и Windows Server 2003). Основное внимание уделяется базовым системным службам, включая управление файловой системой, процессами и потоками, взаимодействие между процессами, сетевое программирование и синхронизацию. Рассматривается методика переноса приложений, написанных в среде Win32, в среду Win64. Подробно описываются все аспекты системы безопасности Windows и ее практического применения. Изобилие реальных примеров, доступных также и на Web-сайте книги, существенно упрощает усвоение материала.
Книга ориентирована на разработчиков и программистов, как высокой квалификации, так и начинающих, а также будет полезна для студентов соответствующих специальностей.
Системное программирование в среде Windows - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
q_insert(q, msg, msize);
/* Сигнализировать о том, что очередь не пуста; мы вставили сообщение.*/
PulseEvent (q->q_ne);
/* Широковещательная модель CV. */
ReleaseMutex(q->q_guard);
return 0;
}
DWORD q_initialize(queue_t *q, DWORD msize, DWORD nmsgs) {
/* Инициализация очереди, включая ее мьютекс и события. */
/* Выделить память для всех сообщений. */
q->q_first = q->q_last = 0;
q->q_size = nmsgs;
q->q_destroyed = 0;
q->q_guard = CreateMutex(NULL, FALSE, NULL);
q->q_ne = CreateEvent(NULL, TRUE, FALSE, NULL);
q->q_nf = CreateEvent(NULL, TRUE, FALSE, NULL);
if ((q->msg_array = calloc(nmsgs, msize)) == NULL) return 1;
return 0; /* Ошибки отсутствуют. */
}
DWORD q_destroy(queue_t *q) {
if (q_destroyed(q)) return 1;
/* Освободить все ресурсы, созданные вызовом q_initialize. */
WaitForSingleObject(q->q_guard, INFINITE);
q->q_destroyed = 1;
free(q->msg_array);
CloseHandle(q->q_ne);
CloseHandle(q->q_nf);
ReleaseMutex(q->q_guard);
CloseHandle(q->q_guard);
return 0;
}
DWORD q_destroyed(queue_t *q) {
return (q->q_destroyed);
}
DWORD q_empty(queue_t *q) {
return (q->q_first == q->q_last);
}
DWORD q_full(queue_t *q) {
return ((q->q_last – q->q_first) == 1 || (q->q_first == q->q_size-l && q->q_last == 0));
}
DWORD q_remove(queue_t *q, PVOID msg, DWORD msize) {
char *pm;
pm = (char *)q->msg_array;
/* Удалить наиболее давнее ("первое") сообщение. */
memcpy(msg, pm + (q->q_first * msize), msize);
q->q_first = ((q->q_first + 1) % q->q_size);
return 0; /* Ошибки отсутствуют. */
}
DWORD q_insert(queue_t *q, PVOID msg, DWORD msize) {
char *pm;
pm = (char *)q->msg_array;
/* Добавить новое ("последнее") сообщение. */
if (q_full(q)) return 1; /* Ошибка – очередь заполнена. */
memcpy(pm + (q->q_last * msize), msg, msize);
q->q_last = ((q->q_last + 1) % q->q_size);
return 0;
}
Комментарии по поводу функций управления очередью с точки зрения производительности
В приложении В представлены данные, характеризующие производительность программы 10.5, в которой используются функции управления очередью. Приведенные ниже замечания по поводу различных факторов, которые могут оказывать влияние на производительность, основываются на этих данных. Программные коды упоминаемых ниже альтернативных вариантов реализации находятся на Web-сайте книги.
• В данной реализации используется широковещательная модель ("вручную сбрасываемое событие/PulseEvent"), обеспечивающая поддержку общего случая, когда один поток может запрашивать или создавать несколько сообщений. Если такая общность не требуется, можно использовать сигнальную модель ("автоматически сбрасываемое событие/SetEvent"), которая, к тому же, обеспечит значительно более высокую производительность, поскольку для тестирования предиката будет освобождаться только один поток. На Web-сайте находится файл QueueObj_Sig.с, содержащий исходный код, в котором вместо широковещательной модели используется сигнальная модель.
• Использование для защиты объекта очереди объекта CRITICAL_SECTION вместо мьютекса также может привести к повышению производительности. Однако в этом случае вместо функции SignalObjectAndWait следует использовать функцию EnterCriticalSection с последующим ожиданием события. Этот альтернативный подход иллюстрируется двумя файлами — QueueObjCS.с и QueueObjCS_Sig.с, находящимися на Web-сайте книги.
• На Web-сайте находятся два других файла с исходными кодами — QueueObj_noSOAW.с и QueueObjSig_noSOAW.с, в которых функция SignalObjectAndWait не используется и которые обеспечивают выполнение программы под управлением Windows 9x.
• Результаты, приведенные в приложении В, свидетельствуют о нелинейном поведении производительности при большом количестве потоков, состязающихся за доступ к очереди. Проекты для каждой из альтернативных стратегий содержатся на Web-сайте книги; эти проекты соответствуют различным вариантам конвейерной системы ThreeStage, описанной в следующих разделах.
•Резюмируя, следует подчеркнуть, что свойства очередей могут быть расширены таким образом, чтобы очередь могла совместно использоваться несколькими процессами и обеспечивать отправку или получение сразу нескольких сообщений за одну операцию. В то же время, некоторого выигрыша в производительности можно добиться за счет использования сигнальной модели, объектов CRITICAL_SECTIONS или функции SignalObjectAndWait. Соответствующие результаты представлены в приложении В.
Пример: использование очередей в многоступенчатом конвейере
Модель "хозяин/рабочий", во всех ее вариациях, является одной из наиболее популярных моделей многопоточного программирования, а программа 8.2 представляет простую модель "производитель/потребитель", являющуюся частным случаем более общей конвейерной модели (pipeline model).
В другом важном частном случае имеется один главный поток, который производит единичные рабочие задания (work units) для ограниченного количества рабочих потоков и помещает их в очередь. Такая методика может оказаться полезной при создании масштабируемого сервера с большим количеством клиентов (число которых может достигать тысячи и более), когда возможность выделения независимого рабочего потока для каждого клиента весьма сомнительна. В главе 14 задача создания масштабируемого сервера обсуждается в контексте портов завершения ввода/вывода.
В конвейерной модели каждый поток или группа потоков определенным образом обрабатывает единичные задания, например, сообщения, и передает их другим потокам для дальнейшей обработки. Аналогом многопоточного конвейера может служить производственная сборочная линия. Идеальным механизмом реализации конвейера являются очереди.
В программе 10.5 (ThreeStage.c) предусмотрено создание нескольких этапов производства и потребления, на каждой из которых поддерживается очередь рабочих заданий, подлежащих обработке. Каждая очередь имеет ограниченную, конечную длину. Всего существует три конвейерных ступени, соединяющих четыре этапа обработки. Программа имеет следующую структуру:
• Производители (producers) периодически создают единичные сообщения, дополненные контрольными суммами, используя для этого ту же функцию, что и в программе 8.2, если не считать того, что в каждом сообщении содержится дополнительное поле адресата, указывающее поток потребителя (consumer), для которой предназначено это сообщение, причем каждый производитель связывается только с одним потребителем. Количество пар "производитель/потребитель" задается в виде параметра командной строки. Далее производитель посылает одиночное сообщение передающему потоку (transmitter), помещая его в очередь передачи сообщений. Если очередь заполнена, производитель ждет, пока ее состояние не изменится.
Читать дальшеИнтервал:
Закладка: