Джонсон Харт - Системное программирование в среде Windows
- Название:Системное программирование в среде Windows
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2005
- Город:Москва • Санкт-Петербург • Киев
- ISBN:5-8459-0879-5
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Джонсон Харт - Системное программирование в среде Windows краткое содержание
Эта книга посвящена вопросам разработки приложений с использованием интерфейса прикладного программирования операционных систем компании Microsoft (Windows 9х, Windows XP, Windows 2000 и Windows Server 2003). Основное внимание уделяется базовым системным службам, включая управление файловой системой, процессами и потоками, взаимодействие между процессами, сетевое программирование и синхронизацию. Рассматривается методика переноса приложений, написанных в среде Win32, в среду Win64. Подробно описываются все аспекты системы безопасности Windows и ее практического применения. Изобилие реальных примеров, доступных также и на Web-сайте книги, существенно упрощает усвоение материала.
Книга ориентирована на разработчиков и программистов, как высокой квалификации, так и начинающих, а также будет полезна для студентов соответствующих специальностей.
Системное программирование в среде Windows - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Таблица 13.3. Коды, воспринимаемые службой (неполный перечень)
Значение | Описание |
---|---|
SERVICE_ACCEPT_STOP | Разрешает посылку команды SERVICE_CONTROL_STOP. |
SERVICE_ACCEPT_PAUSE_CONTINUE | Разрешает посылку команд SERVICE_CONTROL_PAUSE и SERVICE_CONTROL_CONTINUE. |
SERVICE_ACCEPT_SHUTDOWN | Уведомляет службу о прекращении работы системы. Это дает системе возможность послать службе команду SERVICE_CONTROL_SHUTDOWN. |
SERVICE_ACCEPT_PARAMCHANGE | Требуется NT5. Обеспечивает изменение параметров запуска без выполнения самого перезапуска. Соответствующей командой является SERVICE_CONTROL_PARAMCHANGE |
Специфический для службы код
После того как обработчик зарегистрирован и для службы установлено состояние SERVICE_START_PENDING, служба может инициализировать себя и вновь установить свое состояние. Если говорить о преобразованной версии serverSK, то сразу же после того, как сокеты будут инициализированы, а сервер готов к работе с клиентами, должно быть установлено состояние SERVICE_RUNNING.
Обработчик управляющих команд службы
Обработчик управляющих команд службы, то есть функция косвенного вызова, определяемая с помощью функции RegisterServiceCtrlHandlerEx, имеет следующий прототип:
DWORD WINAPI HandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
dwControl — обозначает фактическую управляющую команду, поступившую в обработчик от SCM. До появления NT5 и введения функции RegisterServiceCtrlHandlerEx этот параметр был единственным параметром обработчика.
Всего существует 14 возможных значений параметра dwControl, включая те, которые перечислены в табл. 13.3, хотя некоторые команды поддерживаются только в NT5 или XP. Нас будут интересовать следующие значения, которые используются в примере:
SERVICE_CONTROL_STOP
SERVICE_CONTROL_PAUSE
SERVICE_CONTROL_CONTINUE
SERVICE_CONTROL_INTERROGATE
SERVICE_CONTROL_SHUTDOWN
Разрешены также пользовательские значения, определяемые в интервале 128-255, однако нам они не понадобятся.
dwEventType — обычно принимает значение 0, в то время как ненулевые значения используются для управления устройствами, но рассмотрение этого вопроса выходит за рамки данной книги. Параметр dwEventType определяет дополнительную информацию, которая требуется соответствующим событиям.
Наконец, lpContext — пользовательские данные, передаваемые в функцию RegisterServiceCtrlHandlerEx во время регистрации обработчика.
Обработчик активизируется SCM в том же потоке, что и основная программа, и обычно содержит ряд операторов switch, как будет показано в приведенных ниже примерах.
Пример: "интерфейсная оболочка" службы
Программа 13.2 реализует преобразованный вариант программы serverSK, который мы перед этим обсуждали. Преобразование сервера в службу сопряжено с решением всех ранее описанных задач. После внесения незначительных изменений существующий код сервера помещается в функцию ServiceSpecific. Поэтому представленный ниже код, по сути, является оболочкой (wrapper) существующей программы сервера, точка входа которой main заменена на ServiceSpecifiс.
Другим дополнением, которое здесь не представлено, но включено в вариант программы, находящийся на Web-сайте книги, является использование журнала службы, поскольку службы часто запускаются без интерактивной консоли, никак себя видимо не проявляя.
/* Глава 13. serviceSK.c
Преобразование сервера serverSK в службу Windows.
Несмотря на рассмотрение частного случая, оболочка имеет универсальный характер. */
#include "EvryThng.h"
#include "ClntSrvr.h"
#define UPDATE_TIME 1000 /* Интервал обновления – 1 секунда. */
VOID LogEvent(LPCTSTR, DWORD, BOOL);
void WINAPI ServiceMain(DWORD argc, LPTSTR argv[]);
VOID WINAPI ServerCtrlHandlerEx(DWORD; DWORD, LPVOID, LPVOID);
void UpdateStatus (int, int); /* Вызывает, функцию SetServiceStatus. */
int ServiceSpecific (int, LPTSTR *); /* Ранее программа main. */
volatile static BOOL ShutDown = FALSE, PauseFlag = FALSE;
static SERVICE_STATUS hServStatus;
static SERVICE_STATUS_HANDLE hSStat; /* Дескриптор, используемый при установке состояния. */
static LPTSTR ServiceName = _T("SocketCommandLineService");
static LPTSTR LogFileName = _T("CommandLineServiceLog.txt");
/* Основная процедура, запускающая диспетчер управления службой. */
VOID _tmain(int argc, LPTSTR argv[]) {
SERVICE_TABLE_ENTRY DispatchTable[] = {
{ ServiceName, ServiceMain }, { NULL, NULL }
};
StartServiceCtrlDispatcher(DispatchTable);
return 0;
}
/* Точка входа ServiceMain, вызываемая при создании службы. */
void WINAPI ServiceMain(DWORD argc, LPTSTR argv[]) {
DWORD i, Context = 1;
/* Установить текущий каталог и открыть файл журнала, присоединяемый к существующему файлу. */
/* Определить все элементы структуры состояния сервера. */
hServStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
hServStatus.dwCurrentState = SERVICE_START_PENDING;
hServStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
hServStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIF0C_ERROR;
hServStatus.dwServiceSpecificExitCode = 0;
hServStatus.dwCheckPoint = 0;
hServStatus.dwWaitHint = 2 * CS_TIMEOUT;
hSStat = RegisterServiceCtrlHandlerEx(ServiceName, ServerCtrlHandler, &Context);
SetServiceStatus(hSStat, &hServStatus);
/* Запустить специфическую для службы обработку; выполнение типового участка кода завершено. */
if (ServiceSpecific(argc, argv) != 0) {
hServStatus.dwCurrentState = SERVICE_STOPPED;
hServStatus.dwServiceSpecificExitCode = 1;
/* Ошибка при инициализации сервера. */
SetServiceStatus(hSStat, &hServStatus);
return;
}
/* Возврат сюда будет осуществлен лишь после завершения функции ServiceSpecific, указывающего на прекращение работы системы. */
UpdateStatus(SERVICE_STOPPED, 0);
return;
}
void UpdateStatus(int NewStatus, int Check)
/* Определить новое состояние и контрольную точку — задается либо истинное значение, либо приращение. */
{
if (Check < 0) hServStatus.dwCheckPoint++;
else hServStatus.dwCheckPoint = Check;
if (NewStatus >= 0) hServStatus.dwCurrentState = NewStatus;
SetServiceStatus(hSStat, &hServStatus);
return;
}
/* Функция обработчика, активизируемая SCM для выполнения в том же */
/* потоке, что и основная программа. */
/* Последние три параметра не используются, так что обработчики, написанные*/
/* для версий Windows младше NT5, в этом примере также будут работать. */
VOID WINAPI ServerCtrlHandlerEx(DWORD Control, DWORD EventType, LPVOID lpEventData, LPVOID lpContext) {
switch (Control) {
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
ShutDown = TRUE; /* Установить глобальный флаг завершения. */
UpdateStatus(SERVICE_STOP_PENDING, –1);
break;
case SERVICE_CONTROL_PAUSE:
PauseFlag = TRUE; /* Периодический опрос. */
break;
case SERVICE_CONTROL_CONTINUE:
PauseFlag = FALSE;
break;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
if (Control > 127 && Control < 256) /*Пользовательские сигналы.*/
break;
}
UpdateStatus(-1, –1); /* Инкрементировать контрольную точку. */
Интервал:
Закладка: