Джонсон Харт - Системное программирование в среде Windows
- Название:Системное программирование в среде Windows
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2005
- Город:Москва • Санкт-Петербург • Киев
- ISBN:5-8459-0879-5
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Джонсон Харт - Системное программирование в среде Windows краткое содержание
Эта книга посвящена вопросам разработки приложений с использованием интерфейса прикладного программирования операционных систем компании Microsoft (Windows 9х, Windows XP, Windows 2000 и Windows Server 2003). Основное внимание уделяется базовым системным службам, включая управление файловой системой, процессами и потоками, взаимодействие между процессами, сетевое программирование и синхронизацию. Рассматривается методика переноса приложений, написанных в среде Win32, в среду Win64. Подробно описываются все аспекты системы безопасности Windows и ее практического применения. Изобилие реальных примеров, доступных также и на Web-сайте книги, существенно упрощает усвоение материала.
Книга ориентирована на разработчиков и программистов, как высокой квалификации, так и начинающих, а также будет полезна для студентов соответствующих специальностей.
Системное программирование в среде Windows - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
/* … Стандартный код — для данного примера не является существенным … */
}
fclose(fin);
/* Записать результаты. */
fout = fopen(output_file, "w");
if (fout == NULL) return 2;
fprintf(fout, " %9d %9d %9d %s\n", nl, nw, nc, input_file);
fclose(fout);
return 0;
}
_declspec(dllexport)
int toupperip(char * command, char * output_file)
/* Преобразует входные данные к верхнему регистру; выполняется внутри процесса. */
/* Вторая лексема задает входной файл (первая лексема – "toupperip"). */
{
/* … */
extract_token(1, command, input_file);
fin = fopen(input_file, "r");
if (fin == NULL) return 1;
fout = fopen(output_file, "w");
if (fout == NULL) return 2;
while ((c = fgetc (fin)) != EOF) {
if (c == '\0') break;
if (isalpha(c)) с = toupper(c);
fputc(c, fout);
}
fclose(fin);
fclose(fout);
return 0;
}
static void extract_token(int it, char * command, char * token) {
/* Извлекает из "команды" лексему номер "it" (номером первой лексемы */
/* является "0"). Результат переходит в "лексему" (token) */
/* В качестве разделителей лексем используются пробелы. … */
return;
}
Ориентированные на строки сообщения , точкив хода DLL и TLS
Программы serverSK и clientSK взаимодействуют между собой, обмениваясь сообщениями, каждое из которых состоит из 4-байтового заголовка, содержащего размер сообщения, и собственно содержимого. Обычной альтернативой такому подходу служат сообщения, отделяемые друг от друга символами конца строки (или перевода строки).
Трудность работы с такими сообщениями заключается в том, что длина сообщения заранее не известна, в связи с чем приходится проверять каждый поступающий символ. Однако получение по одному символу за один раз крайне неэффективно, и поэтому символы сохраняются в буфере, содержимое которого может включать один или несколько символов конца строки и составные части одного или нескольких сообщений. При этом в промежутках между вызовами функции получения сообщений необходимо поддерживать неизменным содержимое и состояние буфера. В однопоточной среде для этой цели могут быть использованы ячейки статической памяти, но совместное использование несколькими потоками одной и той же статической переменной невозможно.
В более общей формулировке, мы сталкиваемся здесь с проблемой сохранения долговременных состояний в многопоточной среде (multithreaded persistent state problem). Эта проблема возникает всякий раз, когда безопасная в отношении многопоточного выполнения функция должна поддерживать сохранение некоторой информации от одного вызова функции к другому. Такая же проблема возникает при работе с функцией strtook, входящей в стандартную библиотеку С, которая предназначена для просмотра строки для последовательного нахождения экземпляров определенной лексемы.
Решение проблемы долговременных состояний в многопоточной среде
В искомом решении сочетаются несколько компонентов:
• Библиотека DLL, в которой содержатся функции, обеспечивающие отправку и прием сообщений.
• Функция, представляющая точку входа в DLL.
• Локальная область хранения потока (TLS, глава 7). Подключение процесса к библиотеке сопровождается созданием индекса DLL, а отключение — уничтожением. Значение индекса хранится в статическом хранилище, доступ к которому имеют все потоки.
• Структура, в которой хранится буфер и его текущее состояние. Структура распределяется всякий раз, когда к библиотеке подключается новый поток, и его адрес сохраняется в записи TLS для данного потока. При отсоединении потока от библиотеки память, занимаемая его структурой, освобождается.
Таким образом, TLS играет роль статического хранилища, и у каждого потока имеется собственная уникальная копия этого хранилища.
Пример: безопасная многопоточная DLL для обмена сообщениями через сокет
Программа 12.4 представляет собой DLL, содержащую две функции для обработки символьных строк (в именах которых в данном случае присутствует "CS", от character string — строка символов), или потоковые функции сокета (socket streaming functions): SendCSMessage и ReceiveCSMessage, а также точку входа DllMain (см. главу 5). Указанные две функции играют ту же роль, что и функция ReceiveMessage, а также функции, использованные в программах 12.1 и 12.2, и фактически заменяют их.
Функция DllMain служит характерным примером решения проблемы долговременных состояний в многопоточной среде и объединяет TLS и библиотеки DLL.
Освобождать ресурсы при отсоединении потоков (случай DLL_THREAD_DETACH) особенно важно в случае серверной среды; если этого не делать, то ресурсы сервера, в конечном счете, исчерпаются, что может привести к сбоям в его работе или снижению производительности или к тому и другому одновременно.
Примечание
Некоторые из иллюстрируемых ниже концепций прямого отношения к сокетам не имеют, но, тем не менее, рассматриваются именно здесь, а не в предыдущих главах, поскольку данный пример предоставляет удобную возможность для иллюстрации методов создания безопасных многопоточных DLL в реалистических условиях.
Использующие эту DLL коды клиента и сервера, незначительно измененные по сравнению с программами 12.1 и 12.2, доступны на Web-сайте книги.
/* SendReceiveSKST.с — DLL многопоточного потокового сокета. */
/* В качестве разделителей сообщений используются символы конца */
/* строки ('\0'), так что размер сообщения заранее не известен. */
/* Поступающие данные буферизуются и сохраняются в промежутках между */
/* вызовами функций. */
/* Для этой цели используются локальные области хранения потоков */
/* (Thread Local Storage, TLS), обеспечивающие каждый из потоков */
/* собственным закрытым "статическим хранилищем". */
#define _NOEXCLUSIONS
#include "EvryThng.h"
#include "ClntSrvr.h" /* Определяет записи запроса и ответа. */
typedef struct STATIC_BUF_T {
/* "static_buf" содержит "static_buf_len" байтов остаточных данных. */
/* Символы конца строки (нулевые символы) могут присутствовать, а могут */
/* и не присутствовать. */
char static_buf[MAX_RQRS_LEN] ;
LONG32 static_buf_len;
} STATIC_BUF;
static DWORD TlsIx = 0; /* Индекс TLS – ДЛЯ КАЖДОГО ПРОЦЕССА СВОЙ ИНДЕКС.*/
/* Для однопоточной библиотеки использовались бы следующие определения:
static char static_buf [MAX_RQRS_LEN];
static LONG32 static_buf_len; */
/* Основная функция DLL. */
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
STATIC_BUF * pBuf;
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
TlsIx = TlsAlloc();
/* Для основного потока подключение отсутствует, поэтому во время подключения процесса необходимо выполнить также операции по подключению потока. */
Интервал:
Закладка: