ТОП 10:

Програмне встановлення служби



Перед тим як служба стане доступна для менеджера служб, її потрібно встановити у системі. Встановлення зводиться до занесення відповідної інформації у систем­ний реєстр, його можна робити в окремому застосуванні і у коді самої служби, на­приклад під час виклику її виконуваного файла із певним параметром командно­го рядка. Для встановлення служби використовують функцію CreateService():

SC_HANDLE CreateService(SC_HANDLE mh. LPCTSTR svc_name.

LPCTSTR dispjiame. DWORD access. DWORD svc_type. DWORD start_type.

DWORD err_ctl. LPCTSTR exe_path. LPCTSTR lgrp, LPDWORD tag_id.

LPCTSTR deps. LPCTSTR account. LPCTSTR password):

де: mh - дескриптор менеджера служб, отриманий за допомогою виклику функції OpenSCManagerO;

 

svc_name - ім'я служби, використовуване для її ідентифікації (зокрема, його передають у функції керування службами, воно є параметром утиліти net. ехе тощо);

disp_name - ім'я, відображуване у списку служб вікна керування службами, а також у повідомленнях утиліти net. ехе;

svc_type — тип служби (для звичайних служб, виконуваних в окремому проце­сі, використовують значення SERVICEWIN32 0WNPR0CESS);

start_type - тип запуску служби (SЕRVІСE_DEMAN0_START - запуск на вимогу, SER-VICE_AUTO_START — автоматичний запуск під час завантаження системи);

ехе _path — повний шлях до виконуваного файла служби (якщо службу встанов­люють із її власного коду, для отримання такого шляху можна використати функцію GetModuleFileNameO);

account - ім'я користувача, із правами якого виконуватиметься служба (якщо

NULL — службу виконують із правами спеціального користувача Local System, так роблять найчастіше), password — пароль цього користувача.

 

Функція повертає дескриптор служби. Після завершення роботи зі службою цей дескриптор потрібно закрити за допомогою функції CloseServiceHandleO.

 

char exe_path[1024];

GetModuleFileName(NULL, exe_path. sizeof(exe_path));

SCJANDLE mh = OpenSCManagerС NULL, NULL, SC_MANAGER_ALL_ACCESS):

SC_HANDLE sh - CreateServiceCmh."mysvc"."Служба MySvc".

SERVICE_ALL_ACCESS. SERVICE_WIN32_0WN_PR0CESS. SERVICE_DEMAND_START.

SERVICE_ERR0R_N0RMAL. exe_path. NULL. NULL. NULL. NULL. NULL);

CIoseServi ceHandle(sh);

 

Реалізація коду служби

Перейдемо до безпосередньої реалізації коду служби. Насамперед необхідно ви­значити кілька змінних. Серед них структура SERVICESTATUS, що відображає стан служби, дескриптор стану служби (змінна типу SERVICE_STATUS HANDLE) і прапо­рець, який визначає, чи можна продовжувати виконання основної функції служ­би (змінна running). Ці змінні визначаються як глобальні, тому що до них потріб­ний доступ із кількох функцій (головної функції служби та оброблювача команд керування).

 

SERVICE_STATUS status = { 0 }:

SERVICE_STATUS_HANDLE Sth;

bool running = true:

 

У коді функції mainO необхідно визначити масив структур SERVICETABLEENTRY. Елементами цієї структури є ім'я служби і покажчик на її головну функцію. Для останнього елемента масиву обидва ці поля задаються як NULL. Цю структуру пот­рібно передати як параметр у функцію StartServiceCtrlDispatcherO. Після цього виконуватиметься код головної функції служби.

 

void mainO {

SERVICE_TABLE_ENTRY disp_table[] -

{{"mysvc",svc_main},{NULL.NULL}}:

StartServiceCtrlDispatcher(disptable);

}

 

Головна функція служби

Головну функцію служби викликають під час запуску служби (внаслідок вико­нання StartServiceCtrlDispatcherO) і виконують до її зупинки. її код реалізує основну функціональність служби (очікує з'єднань від клієнтів, виконує запити тощо). Визначення цієї функції має такий вигляд:

 

void WINAPI svc_main(DW0RD argc. LPTSTR argv[]) {

// код основної функції служби

 

У цій функції потрібно виконати ряд кроків. Насамперед задаються деякі па­раметри служби встановленням полів глобальної структури SERVICESTATUS. До них належать:

♦ dwServiceType - тип служби (SERVICE jMIN32j3WN_PR0CESS для звичайних служб, які виконуються в окремому процесі);

♦ dwCurrentState — поточний стан служби (у цей момент вона очікує початку ви­конання, і цей параметр покладають рівним SERVICE_START_PENDING);

 

♦ dwContro Is Accepted - допустимі керуючі команди, які надходитимуть у функ-

цію-обробник команд (SERVICEACCEPTSTOP означає, що оброблятиметься тіль-­

ки команда Stop).

Заповнення структури SERVICESTATUS виконується так:

status.dwServiceType = SERVICE_WTN32_0WN_PR0CESS;

status.dwCurrentState - SERVICE_START_PENDING;

status.dwControlsAccepted - SERVICE_ACCEPT_STOP:

 

Після цього необхідно зареєструвати у системі оброблювач керуючих команд цієї служби за допомогою функції RegisterServiceCtrlHandlerO, що приймає ім'я служби та адресу функції-обробника, а повертає глобальний дескриптор статусу служби.

 

sth = RegisterServiceCtrlHandler("mysvc",svc_ctrlhandler):

 

Після виконання цього виклику служба матиме змогу реагувати на керуючі команди (наприклад, на команду зупинки служби).

На цьому підготовчий етап завершують. Тепер можна ініціалізувати службу (створити мережні з'єднання, підготувати внутрішні структури даних тощо). Пі­сля цього службу переводять у стан виконання, для чого задають нове значення поля dwCurrentState для структури SERVICESTATUS і викликають функцію SetServi -ceStatusO, першим параметром якої є глобальний дескриптор статусу служби, а другим — покажчик на структуру SERVICESTATUS.

 

// ... ініціалізація служби

status.dwCurrentState - SERVICERUNNING;

SetServiceStatus(sth. Sstatus);

 

Після цього служба може виконувати будь-які дії, яких від неї вимагатиме програміст (приймати з'єднання від клієнтів тощо).

 

while (running) {

// ... робота служби

}

 

У даному разі змінна runni ng асинхронно змінюватиметься в оброблювачі ко­манд керування.

 

Оброблювач команд керування

Функцію-оброблювач команд керування викликають асинхронно у разі отриман­ня службою такої команди (наприклад, за допомогою вікна керування службами або утиліти net. ехе). Ця функція схожа на оброблювач сигналів у UNIX або об­роблювач консольних команд Windows ХР. Вона має приймати один параметр, що відображає команду керування, і виконувати дії залежно від значення цієї ко­манди. У наведеному прикладі ця функція обробляє тільки команду Stop Service (SERVICEC0NTR0LST0P); можна обробляти й інші команди, наприклад Pause/Con­tinue або Shutdown, яку подають у разі припинення роботи ОС. У коді оброблюва­ча змінюють статус служби і значення глобальної змінної running, яке перевіря­ють в основній функції служби.

 

void WINAPI svc_ctrlhandler(DWORD ctl) {

if (ctl ™ SERVICE_C0NTR0L_ST0P) {

status.dwCurrentState - SERVICE_STOPPED;

SetServiceStatus(sth.&status);

running » false:

 

Вилучення служби

Для вилучення служби із реєстру використовують функцію DeleteService(), куди необхідно передати дескриптор служби. Його потрібно отримати за допомогою функції OpenService(), що як параметри приймає дескриптор менеджера служб та ім'я наявної служби:

 

SC_HANDLE mh - OpenSCManager(NULL.NULL.SC_MANAGER_ALL_ACCESS);

SC_HANDLE sh - OpenServicetmh."mysvc",SERVICE_ALL_ACCESS):

DeleteService(sh);

CIoseServi ceHandle(sh):

 

Зазначимо, що якщо служба в момент вилучення перебувала у стані виконан­ня, її лише позначають для вилучення. Фактичне вилучення відбувається під час наступного завантаження системи.

 

Висновки

♦ Термінальне введення-виведення реалізує взаємодію з алфавітно-цифровими пристроями. У сучасних ОС такі пристрої найчастіше є емуляторами терміна­ла, роботу із якими здійснюють за одними й тими самими правилами. На осно­ві термінального введення-виведення реалізують командний інтерфейс кори­стувача ОС у вигляді командних інтерпретаторів.

♦ Є різні підходи до організації графічного інтерфейсу користувача, найпоши­ренішим із них є реалізація такого інтерфейсу як інтегрованої частини систе­ми, що працює в режимі ядра (так зроблено у системах лінії Windows ХР), і реалізація засобів його підтримки в режимі користувача у вигляді набору бібліотек та утиліт (прикладом є система X Window).

♦ Розробка фонових застосувань, що не взаємодіють із користувачем, здійснюється за особливими правилами. В UNIX-системах для таких застосувань закрито можливість інтерактивного обміну даними із користувачем, у системах лінії Windows ХР є спеціальний компонент, відповідальний за керування ними.

 

Контрольні запитання та завдання

1. Наведіть приклад програмного каналу, один із елементів якого має завершитися аварійно через одержання сигналу SIGPIPE. Використовуйте синтаксис каналів командного інтерпретатора.

2. Розробіть застосування для Linux і Windows ХР, яке:

а) створює нащадка, переадресовує свій стандартний вивід на стандартний ввід цього нащадка, виводить повідомлення на стандартний вивід і від­новлює попередній стан виводу. Нащадок повинен відображати на стан­дартний вивід усі дані, отримані на його стандартний ввід;

б) переадресовує стандартний вивід і стандартний потік повідомлень про по­милки в кінець файла, ім'я якого задано в командному рядку, після чого виводить повідомлення на стандартний вивід і в стандартний потік пові­домлень про помилки;

в) створює двох нащадків і переадресовує стандартний вивід одного з них на стандартний ввід іншого (зв'язуючи їх безіменним каналом). Перший на­щадок повинен виводити довільне повідомлення на стандартний вивід, другий - відображати на стандартний вивід усі дані, отримані на стан­дартний ввід;

г) зберігає стандартний вивід нащадка в рядку символів і відображає вміст цього рядка (так може бути реалізована командна підстановка). Нащадок повинен виводити довільне повідомлення на стандартний вивід.

3. Модифікуйте застосування завдання 2, б з розділу 17 так, щоб стандартний потік повідомлень про помилки був спрямований на сервер (заданий ІР-адре-сою і портом) з використанням сокетів. Розробіть сервер, що буде зберігати от­риману інформацію у файлі.

4. Модифікуйте командний інтерпретатор для Linux і Windows ХР, розроблений під час виконання завдання 10 з розділу 3 і завдання 10 з розділу 14, доповнив­ши його функцією переадресування введення-виведення, каналів і командної підстановки. Під час розв'язання задачі користуйтеся результатами виконання завдання 2 з розділу 17.

5. Сесія командного інтерпретатора запущена для віддаленого телнет-клієнта. Опишіть, які компоненти ОС на локальному і віддаленому хостах відпові­дають за відображення стандартного виводу застосувань, запущених у цій сесії.

6. Перелічіть спільні риси та відмінності віконної підсистеми Windows ХР і сис­теми X Window. Які переваги і недоліки має кожна із систем?

7. Сесія командного інтерпретатора, запущена на віддаленому хості, відображаєть­ся у вікні емулятора термінала xterm. Опишіть, які компоненти ОС на локаль­ному і віддаленому хостах відповідають за відображення стандартного виводу застосувань, запущених у цій сесії.

8. У якій ситуації стандартний вивід Х-клієнта автоматично відображається на текстовій консолі, з якої був запущений Х-сервер, а в якій - ні? Чи можна за­безпечити відображення виводу Х-клієнта на задану текстову віртуальну кон­соль?

9. Розробіть фонове застосування для Linux і Windows ХР, що відстежує всі зміни файлів у заданому каталозі (створення, вилучення, зміну розміру тощо). Ім'я каталогу може бути задане в командному рядку, для Windows ХР допус­тиме його задания в системному реєстрі. Кожну зміну реєструють у файлі у форматі "час: ім'я_файлу характер_зміни".

10. Модифікуйте сервер, одержаний для завдання 11 з розділу 16, реалізувавши його як фоновий процес для Linux і Windows ХР.

 

 

Розділ 16







Последнее изменение этой страницы: 2017-02-06; Нарушение авторского права страницы

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 35.175.121.230 (0.009 с.)