Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатика
ИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханика
ОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторика
СоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансы
ХимияЧерчениеЭкологияЭкономикаЭлектроника

Точка входа main

Читайте также:
  1. ATP-III. Метаболический синдром как вторичная точка приложения терапии
  2. I. Я КАК ТОЧКА НАБЛЮДЕНИЯ
  3. А. ЭНЕРГЕТИЧЕСКАЯ ТОЧКА КРЕСТЦОВОЙ ПОМПЫ
  4. Альтернативная точка зрения
  5. В поисках входа
  6. В. ТОЧКА НАДПОЧЕЧНИКОВ Т-11
  7. Вера в Иисуса как необходимое условие для входа в царство небесное

Основная задача main – вызов функции StartServiceCtrlDispatcher. Данная функция осуществляет подключение сервиса к SCM и запускает поток обработки команд. Возврат из данной функции производится по завершении всех сервисов процесса. Данная функция в качестве аргумента принимает массив структур, содержащих имя сервиса и точку входа в данный сервис – для каждого сервиса данного процесса.

Внутри функции WinMain (main) мы инициализируем структуру SERVICE_TABLE_ENTRY, которая выглядит так:

typedef struct _SERVICE_TABLE_ENTRY {

LPTSTR lpServiceName;

LPSERVICE_MAIN_FUNCTION lpServiceProc;

} SERVICE_TABLE_ENTRY, *LPSERVICE_TABLE_ENTRY;

Первый параметр структуры - имя сервиса, а второй - адрес callback-функции ServiceMain. Поскольку шаблон процесса содержит только один сервис, то должно быть два элемента структуры SERVICE_TABLE_ENTRY в массиве - один для сервиса и второй нулевой (NULL) для указания конца массива.

Затем, адрес этого массива мы передаем функции StartServiceCtrlDispatcher:

BOOL StartServiceCtrlDispatcher(LPSERVICE_TABLE_ENTRY lpServiceStartTable);

Эта API-функция, как и исполняемый процесс, посылает SCM уведомления от сервисов, находящихся в процессе. StartServiceCtrlDispatcher создает новый поток для каждого ненулевого элемента массива SERVICE_TABLE_ENTRY, переданного ей в качестве параметра. Созданный поток, начинает свою работу с функции ServiceMain, которая определена в члене lpServiceProc структуры.

SCM отслеживает процесс запуска сервиса. Например, после того, как SCM запускает сервис, он входит в режим ожидания, пока основной поток исполняемого файла оболочки вызовет StartServiceCtrlDispatcher. Если StartServiceCtrlDispatcher основным потоком не вызвана, SCM считает, что в реализации сервиса присутствует ошибка и вызывает функцию TerminateProcess для завершения процесса. По этой причине, если Ваш процесс требует более 2 минут для инициализации, Вы должны сами создать отдельный поток, в котором будет происходить инициализация, позволив основному потоку как можно быстрее выполнить StartServiceCtrlDispatcher. После завершения работы функция StartServiceCtrlDispatcher не сразу возвращает управление в функцию WinMain (main). Вместо этого она создает цикл (наподобии цикла сообщений стандартных исполняемых файлов см. код ниже).

Цикл StartServiceCtrlDispatcher

// нулевые значения массива не читаются

int nNumRunningServices = NumElementsInServiceStartTable - 1;

while (nNumRunningServices > 0) {

WaitForAServiceControlCodeOrAServiceThreadToTerminate();

if (AServiceControlCode) {

RemoveServiceControlCodeFromQueue()

CallServiceHandler(fdwControlCode);

} else {

nNumRunningServices--;

}

}

return(TRUE);

// StartServiceCtrlDispatcher возвращает управление в WinMain/main

Находясь в этом цикле функция StartServiceCtrlDispatcher "засыпает" в ожидании одного из двух событий:

SCM желает послать уведомление одному из сервисов процесса. Когда уведомление получено, поток "просыпается" и вызывает на выполнение функцию Handler данного сервиса. Функция Handler в свою очередь обрабатывает полученное уведомление (обычно взаимодействуя с потоком сервиса) и возвращает управление функции StartServiceCtrlDispatcher, которая снова входит в цикл и "засыпает" в ожидании нового уведомления.

Один из потоков сервиса прекращает работу. В этом случае функция StartServiceCtrlDispatcher "просыпается" и уменьшает счетчик работающих сервисов на единицу. Если счетчик равен 0 (т.е. все сервисы остановлены), StartServiceCtrlDispatcher возвращает управление функции WinMain (main) для того, чтобы можно было произвести очистку ресурсов системы и завершить процесс. Если, по крайней мере, один из сервисов еще работает, функция StartServiceCtrlDispatcher будет находится в цикле ожидания уведомлений или завершения работы очередного сервисного потока.

Обычно функция ServiceMain игнорирует оба передаваемых ей параметра, поскольку сервисы чаще всего не используют параметров вовсе. Лучшим способом настройки сервиса является получение параметров настройки из реестра. Сервис должен использовать функции доступа к реестру для поиска своих параметров в ключе HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ServiceName\Parameters, где ServiceName - название сервиса. Конечно, можно написать приложение, имеющее пользовательский интерфейс, с помощью которого пользователь сможет изменять настройки сервиса. В таком случае приложение должно сохранять параметры настройки сервиса в реестре, откуда сервис впоследствии сможет их получить. Работающий сервис может использовать API-функцию RegNotifyChangeKeyValue для получения уведомлений о внесении изменений в реестр. Это позволит сервису изменять свои параметры, как говорится, "на лету".


Дата добавления: 2015-08-13; просмотров: 56 | Нарушение авторских прав


Читайте в этой же книге: Службы Windows. | Диспетчер управления сервисами (SCM) | Программы управления сервисами | Учетные зависи сервиса | Начало работы сервиса | Выполнение сервиса | Пример функций сервиса. | Отладка сервиса. |
<== предыдущая страница | следующая страница ==>
Структура программы сервиса| Точка входа в сервис (ServiceMain)

mybiblioteka.su - 2015-2024 год. (0.007 сек.)