Методические указания к курсовой работе по дисциплине «Системное программирование и операционные системы»




НазваниеМетодические указания к курсовой работе по дисциплине «Системное программирование и операционные системы»
страница6/11
Дата публикации05.03.2013
Размер1.32 Mb.
ТипМетодические указания
uchebilka.ru > Математика > Методические указания
1   2   3   4   5   6   7   8   9   10   11
^

Тема 14. Просмотрщик таблицы разделов и FAT.


Техническое задание.

Разработать приложение Windows для просмотра в удобной форме информации о таблице размещения файлов FAT и разделов диска.

Методические указания.

Смотри методические указания к теме 3.

Тема 28. Утилита MaxSplitter

Техническое задание.

Разработать утилиту для разделения длинных файлов на части заданной фиксированной длины. Эта же утилита должна, при задании определенных опций, восстанавливать исходный файл.

Методические указания.

Смотри методические указания к теме 15.

Тема 16. Утилита удаленного администрирования.

Техническое задание.

Разработать утилиту для управления удаленным компьютером.

Методические указания.

Сервер удаленного доступа.

Необходимо построить внутрисистемный интерфейс сервера удаленного доступа, то есть определить способ взаимодействия потоков сервера с программой, производящей выполнение пользовательских запросов. Например, пользовательские запросы могут поступать в командный интерпретатор COMMAND.COM. Для организации взаимодействия с командным интерпретатором можно использовать механизм неименованных каналов (для Windows 95/98) или именованных каналов (Named Pipes) для Windows NT/2000.

Канал имеет два файловых идентификатора - один для записи данных, другой - для чтения имеющейся в канале информации. Порядок продвижения байтов в канале - FIFO (первый поступивший байт первым оказывается на выходе). С помощью API функции CreateProcess можно запустить командный процессор, но при этом стандартные ввод и вывод перенаправить на каналы.

Функция CreatePipe создает канал, предоставляемый программисту в виде "двух концов" - идентификаторов:
^

BOOL CreatePipe(


PHANDLE hReadPipe, // address of variable for read handle

PHANDLE hWritePipe, // address of variable for write handle

LPSECURITY_ATTRIBUTES lpPipeAttributes,//security attributes

DWORD nSize // number of bytes reserved for pipe

);

hReadPipe и hWritePipe - указатели на идентификаторы. Идентификаторы получают значение при выполнении этой функции.

lpPipeAttributes - в Win95/98 можно указать просто NULL.

nSize- предположительный размер буфера. Система опирается на это значение для вычисления реального размера буфера. Этот параметр может быть равным нулю. В этом случае система выберет размер буфера "по умолчанию".

Если канал создан, функция возвратит ненулевое значение, в случае ошибки - вернет нуль.

Для операций с каналами используются функции ReadFile и WriteFile. Причем операция чтения завершается только после того, как будет что-нибудь прочитано из канала, а операция записи завершается после помещения данных в собственную очередь канала. Если очередь пуста, ReadFile не завершиться, пока в трубку не поместит данные другой процесс или поток с помощью функции WriteFile. Если очередь заполнена то WriteFile не завершиться до тех пор, пока другой процесс или нить не прочитает данные из каала с использованием ReadFile.

Рассмотрим фрагмент программы на Object Pascal, в котором используются каналы и функция CreateProcess для обмена данными с COMMAND.COM.
var

stinfo: TStartupInfo;

prinfo: TProcessInformation;

ReadPipe,WriteToCommand,ReadFromCommand,WritePipe: integer;

// обнуляем поля структур для CreateProcess

FillChar(stinfo,sizeof(TStartupInfo),0);

FillChar(prinfo,sizeof(TProcessInformation),0);

// пытаемся выполнить CreatePipe для первого и второго канала

if (not CreatePipe(ReadPipe,WriteToCommand,nil,PipeSize)) or

(not CreatePipe(ReadFromCommand,WritePipe,nil,PipeSize)) then

ErrorCode:=1

else

begin

stinfo.cb:= sizeof(stinfo);

stinfo.lpReserved:= nil;

stinfo.lpDesktop:= nil;

stinfo.lpTitle:= nil;

stinfo.dwFlags:=STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;

stinfo.cbReserved2:= 0;

stinfo.lpReserved2:= nil;

stinfo.hStdInput:= ReadPipe;

stinfo.hStdOutput:= WritePipe;

stinfo.hStdError:= WritePipe;

stinfo.wShowWindow:= SW_HIDE;

// запускаем COMMAND.COM

CreateProcess(CommandPath,nil,nil,nil,true,

CREATE_DEFAULT_ERROR_MODE or NORMAL_PRIORITY_CLASS,

nil,CurrentDirectory, stinfo,prinfo)
Для реализации обмена данными с каналами удобно создать два потока, один из которых занимается считыванием символов и их постановкой в очередь на обработку, а другой - передачей символов из очереди в канал.

Другой вариант - вместо отдельных очередей реализовать механизм Callback – процедур по аналогии с оконными процедурами в Windows. В таком случае потоки будут вызывать указанную им процедуру по мере надобности, т.е. если из досовской сессии поступает какая-либо информация, то вызывается процедура обработки входящих символов, а если есть возможность для передачи информации в сеанс MS-DOS - вызывается процедура передачи символов. Причем в последнем случае, возможно, не будет подлежащих передаче данных, тогда вызванная процедура должна сообщить об этом вызывающему потоку специальным зарезервированным кодом. Таким образом, существует два основных способа обмена информацией с каналами - асинхронный, когда используются Callback- процедуры и синхронный - с использованием очередей ввода-вывода.

Следует учесть некоторые детали, касающиеся разделения потоками общих ресурсов. Необходимо гарантировать, что при обращении к очереди из основного потока программы мы не прервем операции с тои же очередью, производимые другими потоками, работающими с каналами. Для синхронизации доступа можно использовать механизм критических секций или мьютексов.

Обеспечение обслуживания клиентов - неотъемлемая функция любого сервера удаленного доступа. Обслуживание клиента состоит из четырех основных стадий:

  • Аутентификация при подключении клиента;

  • Подготовка рабочей среды, т.е. выделение ресурсов на обслуживание;

  • Собственно процесс обслуживания, состоящий в выполнении клиентских запросов и отсылке сообщений о результатах;

  • Отключение клиента и освобождение выделенных ресурсов;

Для осуществления многоканального обслуживания удобно использовать механизм сокетов.

В данном случае аутентификация заключается в запросе пароля у пользователя и проверке правильности введенного слова. Процесс аутентификации можно реализовать в виде отдельного потока, внутри которого происходит циклический опрос сокета пользователя на предмет наличия введенных символов. Время опроса и длина вводимой цепочки символов ограничена соответственно 30 секундами и 32 символами. Символы с кодом менее 32 (пробел) считаются признаком конца строки. После того, как пароль будет введен, выполняется проверка введенного слова на наличие в списке допустимых паролей. Если список не содержит такого слова, то пользователю отправляется сообщение о неудачной попытке и связь разрывается, после чего завершается и сам поток. В случае правильного ввода пароля происходит инициализация другого потока, производящего запуск ДОСовской сессии или подключение к уже запущенной сессии.

Для выделения ресурсов используется поток, внутри которого происходит запуск командного интерпретатора. Сразу же после запуска инициализируются потоки ввода-вывода данных, а управляющий поток переходит в режим ожидания завершения работы командного интерпретатора. Каждая сессия имеет специальную структуру-описатель, в которой хранится состояние соединения, ссылка на сокет клиента и ссылка на поток, запустивший командный интерпретатор. Указатель на эту структуру храниться в списке пользователей и паролей, который, в свою очередь, заполняется информацией при инициализации программы-сервера на основании файла PASSWORDS.LST. Сама структура формируется непосредственно перед активизацией сессии.

Обслуживание клиентов происходит следующим образом: обработчик события, возникающего при поступлении информации от клиента, направляет поступающие данные (символы, строки) на входную очередь потока который переносит данные через канал (pipe) в командный интерпретатор или в запущенную из него программу на стандартное устройство ввода (STDIN). Для того чтобы поступающие данные попадали в требуемый сеанс MS-DOS, сокет-источник данных сравнивается с сокетом в структуре-описателе сесии Когда командный интерпретатор или запущенная из него программа пытается осуществить вывод символов на стандартное устройство вывода (STDOUT) происходит передача символов через канал в поток, контролирующий выходящий из сеанса MS-DOS поток. Этот поток вызывает Callback функцию, которая на основании данных из структуры-описателя осуществляет передачу информации через требуемый сокет.

Отключение клиента осуществляется либо по инициативе клиента, либо по инициативе администратора, либо в результате сбоя в канале обмена данными. Если клиент завершил свою сессию командой EXIT, то ожидающий завершения командного интерпретатора поток сам инициализирует процесс завершения соединения. Во всех этих случаях механизм реализации отсоединения одинаков. Просто производится завершение соединения на требуемом сокете и изменение содержимого полей соответствующей структуры-описателя. Если же происходит завершение работы командного интерпретатора, то структура-описатель уничтожается, что свидетельствует о необходимости повторного создания сеанса MS-DOS при присоединении клиента. Если клиент отсоединился, не завершив работу своего командного интерпретатора, то вся обработка, инициированная отключившимся клиентом на сервере, продолжается без участия клиента. В таком случае, при повторной установке соединения, клиенту будет предоставлена та же сессия, которую он покинул, но, возможно, с продолжающимся или завершенным процессом выполнения ранее данного задания.

Сервер и клиент могут также использовать для работы протокол UDP. Можно поддерживать следующие возможности: перехват мышки, перехват клавиатуры, удалённое управление файлами, изменение разрешения дисплея. Также можно настроить передачу картинки и мышки с удалённого компьютера.

Тема 17. Простая почтовая программа на основе протокола SMTP.

Техническое задание.

Разработать простую почтовую программу.

Методические указания.

Использование сокетов (асинхроная работа). Работа с SMTP сервером, сценарий отправки e-mail. Создание простого GUI на API.

Работа с сокетами на уровне WinSock API описана в Приложении 1.

Коммуникационная модель SMTP описана в документах RFC 821, RFC 822, RFC 1651.

Основные команды SMTP приводятся в Приложении 3.

Формат заголовков SMTP приводится в Приложении 4.

Тема 18. FTP - клиент.

Техническое задание.

Программный продукт должен быть реализован с использованием WinSock API, соединение устанавливается на портах 20 и 21 протокола ТСР. Среда разработки VC++. Реализации подлежат основные команды протокола FTP, которые дадут возможность взаимодействия с одной из стандартных программ FTP-сервер.

Методические указания.

Ориентировочный алгоритм работы клиента FTP:

  1. Осуществляет подключение к серверу FTP

  2. Получает приветствие от сервера

  3. Отправляет сообщение USER с указанным идентификатором ID пользователя серверу и ожидает ответа.

  4. При получении ответа на команду USER отправляет команду PASS с указанным паролем.

  5. При получении положительного ответа на команду PASS запрашивает имя и путь текущего каталога, отправляя команду PWD на сервер.

  6. Получив ответ на команду PWD, выполняет синтаксический разбор, для того, чтобы определить каталог и путь ответного сообщения, и отображает его для пользователя. Для отображения у пользователя содержимого каталога необходимо подготовиться к приему списка каталогов. Клиент выдает команду TYPE, указывающую тип передачи данных ASCII.

  7. Получив ответ на команду TYPE , сервер переходит в пассивный режим, чтобы клиент мог инициализировать соединение данных. Для этого приложение выдает команду PASV.

  8. При получении ответа на команду PASV выполняется синтаксический анализ ответного сообщения для извлечения адреса TCP/IР и порта службы для использования. Клиент использует этот адрес и порт при соединении и создании гнезда данных клиента.

  9. После создания гнезда данных и подсоединения его к адресу, указанному в ответе на команду PASV, отправляет команду LIST, для того чтобы получить список каталогов от сервера.

  10. Когда гнездо данных получает список каталогов, добавляет полученный текст в окно списка, в котором отображен список для пользователя.

  11. Получив положительное завершение списка каталогов, переходит в режим ожидания, пока пользователь выберет операцию для выполнения.

  12. Если пользователь выполняет двойной щелчок на списке каталогов от сервера FTP, то он изучает выбранную строку, для того чтобы определить, выбран каталог или файл. Если пользователь выбрал каталог, клиент отправляет серверу команду CWD с каталогом, в который осуществляется перемещение. Получив положительный ответ от команды CWD, клиент повторяет предыдущие действия, начиная с действия 5 (выдача команды PWD серверу)

  13. Если пользователь выбирает файл, начинает отправлять последова­тельность команд серверу для подготовки к извлечению выбранного файла. Первое из указанных действий предусматривает отправление команды TYPE серверу с указанием типа данных Image, после чего выполняется отправление команды PASV серверу.

После перехода сервера в пассивное состояние и соединения гнезда данных клиент отправляет команду RETR с указанием файла для извлечения.

При получении предварительного ответа от команды RETR клиент вводит на хранение в указанный файл все полученные данные.

При получении всего файла клиент закрывает файл и гнездо данных и возвращается в режим ожидания.

  1. Если пользователь выбирает файл для отправления серверу, то он выполняет практически те же действия, что и при извлечении файла. Вместо отправления команды RETR клиент отправляет команду STOR на сервер.

Получив предварительный ответ на команду STOR, клиент открывает выбранный файл и отправляет его по соединению гнезда данных.

После отправления всего файла клиент закрывает соединение данных и возвращается в режим ожидания.

  1. Если пользователь щелкает на кнопке Quit, то он отправляет команду Quit серверу.

  2. Получив команду Quit, сервер закрывает соединение.


Работа с сокетами на уровне WinSock API описана в Приложении 1.

Коммуникационная модель FTP описана в документе RFC 959.

Основные команды FTP приводятся в Приложении 2.

Тема 19. FTP - сервер.

Техническое задание.

Программный продукт должен быть реализован с использованием WinSock API, соединение устанавливается на портах 20 и 21 протокола ТСР. Среда разработки VC++. Реализации подлежат основные команды протокола FTP, которые дадут возможность взаимодействия с одной из стандартных программ FTP-клиент.

Методические указания.

Ориентировочный алгоритм работы сервера FTP

1. Создает гкездо прослушивания и связывает его с портом 21 TCP (FTP по умолчанию).

2. Переводит гнездо в режим прослушивания в ожидании поступающих запросов на соединение.

3. После получения запроса на соединение принимает соединение и создает новое гнездо.

4. Если сервер уже имеет открытое соединение гнезда, отправляет сообщение об отказе новому соединению и затем сразу же закрывает соединение.

5. Если у сервера еще нет активного соединения, он отправляет приветствие клиенту. После отправления ответа клиенту сервер переходит в режим ожидания до- тех пор, пока клиент не сделает следующий запрос.

6. Возвращает сообщение ответа. Если сервер получает команду USER, он возвращает сообщение ответа об успехе. Если сервер получает команду PASS, он отправляет сообщение с положительным ответом.

7. Ожидает, пока будет принята команда от клиента. Командами, которые принимает сервер, являются PORT, TYPE, MODE, RETR, STOR, PWD, XPWD, LIST, NLST, QUIT. На все другие команды сервер отвечает сообщением об ошибке.

8. Получив команды LIST, NLST, STOR или RETR, создает гнездо данных, подсоединяет его к клиенту, а затем запускает передачу данных.

9. После завершения передачи данных закрывает соединение данных.

10. Получив команду QUIT от клиента, отправляет прощальное сообщение и закрывает соединение.
Работа с сокетами на уровне WinSock API описана в Приложении 1.

Коммуникационная модель FTP описана в документе RFC 959.

Основные команды FTP приводятся в Приложении 2.

Тема 20. Системные сервисы Windows NT/2000.

Техническое задание.

Предложить и реализовать новый системный сервис.

Методические указания.

Любая ОС нуждается в средствах для запуска фоновых задач, т.е. таких, которые постоянно работают в памяти, не обращая внимания, кто использует машину. Эти фоновые приложения могут выполнять различные действия в системе. К примеру, система обработки сообщений может наблюдать за сетью и выводить диалоговое окно всякий раз при получении сообщения от другой машины. Приложению, которое посылает и получает факсы, необходимо стартовать при загрузке ОС и продолжать отслеживать поступление новых факсов во все время работы компьютера. Всем этим задачам необходимо время CPU для выполнения своей работы, но они должны это делать, не отвлекая пользователя, т.к. все эти задачи требуют небольшого времени работы CPU.

В MS-DOS такие фоновые программы назывались TSR (Terminate and Stay Resident). Они запускались в autoexec.bat. В UNIX фоновые программы называются "демонами". В Windows NT фоновые программы называются сервисами. Сервисы стартуют автоматически, когда NT загружается, и остаются запущенными в фоновом режиме, не обращая внимания, кто, и с какими правами вошел в систему.

Сервисы Windows NT выполняются как обычные exe файлы, но они должны поддерживать специфичный внутренний протокол, позволяющий им корректно взаимодействовать с SMC (Service Control Manager).

Основные понятия

Сервисы бывают двух видов. Сервисы драйверов устройств используют специальный протокол для взаимодействия с железом. Сервисы Win32, с другой стороны, выполняют большинство фоновых задач, используя вызовы Win32 API. В данной курсовой работе предлагается рассмотреть именно эти сервисы. Любой программист с NT SDK (или Visual C++) и правами доступа администратора к машине с NT может разработать и установить свой собственный сервис. В общем, если Вам необходимо написать какую-либо программу, которая стартует при запуске NT, работает в фоновом режиме, то Вам необходимо создать сервис Win32.

Сервисы видны пользователю в панели управления. Запустив Service Applet, вы увидите список доступных сервисов. Вы можете запускать, останавливать, ставить сервисы на паузу. Нажав кнопку Startup, Вы можете изменить поведение сервиса при запуске. Сервисы могут запускаться автоматически при старте компьютера, быть абсолютно выключеными или иметь возможность запуска вручную. Если сервис запускается вручную, то пользователь может указать параметры запуска. Вам нужно иметь права доступа администратора или права power user, чтобы что-либо делать с сервисами.

Windows NT загружает некоторое количество предустановленных сервисов, таких как network messaging, command shedulling и RPC naming. После создания своего собственного сервиса Вы должны выполнить отдельно инсталляцию, чтобы включить его в список. В процессе установки в реестр добавляется информация о новом сервисе - его имя, имя исполняемого файла и т.п. Это позволит SCM узнать о новом сервисе при последующей перезагрузке.
^

Создание нового сервиса


Как уже было сказано, сервис - это обычный выполняемый файл, но поддерживающий интерфейс с SCM. Microsoft очень аккуратно следит за ходом вызова функций, и Вы обязаны тщательно следовать плану по разработке сервисов, предложенному Microsoft. В ином случае сервис работать не будет. Более подробную информацию Вы найдете в хэлпе.

  • В коде сервиса обязательно должны быть или main, или WinMain. В ходе выполнения main должна немедленно вызвать StartServiceCrtlDispatcher. Вызывая эту функцию, Вы инициализируйте указатель на функцию ServiceMain. Этот указатель будет использован SCM для запуска сервиса.

  • SCM вызывает ServiceMain когда, к примеру, администратор нажимает кнопку Start в ServiceApplet. Выполнение ServiceMain происходит в отдельном потоке. ServiceMain должна вызвать RegisterServiceCtrlHandler, которая, в свою очередь, регистрирует ф-ию Handle для SCM. Handle обрабатывает запросы SCM, о них будет сказано ниже. Вы можете присвоить данной ф-ий любое имя, не обязательно Handle, просто в документации она названа Handle. Ф-ия RegisterServiceCtrlHandler возвращает хэндл, который сервис может использовать, когда нужно послать сообщение SCM.

  • Ф-ия ServiceMain обязана также создать и запустить поток, выполняющий собственно код сервиса. Функция ServiceMain не должна заверщать свою работу, пока сервис работает. Когда ServiceMain завершает работу, сервис останавливается.

  • Функция Handle пытается определить, какой из запросов был получен от SCM.

    • SERVICE_CONTROL_STOP - Говорит сервису, что надо остановиться.

    • SERVICE_CONTROL_PAUSE - Сервис должен стать на паузу.

    • SERVICE_CONTROL_CONTINUE - Говорит сервису, что надо продолжить работу.

    • SERVICE_CONTROL_INTERROGATE - Говорит сервису, что тому следует немедленно сообщить свой статус.

    • SERVICE_CONTROL_SHUTDOWN - Говорит сервису, что скоро будет выключение компьютера .

Также возможно создание собственных констант (со значениями от 128 до 255) и посылка их сервису от SCM.

После того, как Вы создали exe файл, который содержит функции main, ServiceMain, Handler, также как и функцию, содержащую поток сервиса, считайте, что сервис создан. На рисунке показано отношение SCM и перечисленных функций.



   В листинге 1 показан простейший из сервисов. Он просто издает звуки каждые две секунды. Вы можете модифицировать этот интервал, задавая предстартовые параметры. Это полностью законченный сервис, реагирующий на все команды от SCM. По этой причине Вы можете использовать его как шаблон для Ваших сервисов. Ф-ия main вызывает StartServiceCrtlDispatcher для регистрации ф-ии ServiceMain. Эта регистрация выполняется с использованием структуры SERVICE_TABLE_ENTRY. В нашем случае программа содержит только один сервис, поэтому есть только одна точка входа в таблицу. Однако возможно создание нескольких сервисов в одном exe. В этом случае будет идентифицирована соответствуюшая ServiceMain для каждого сервиса. Также возможно следующее: поместить некоторый код инициализации в ф-ию main до вызова StartServiceCrtlDispatcher, но этот код должен быть выполнен не более чем за 30 секунд, иначе SCM прервет выполнение работы сервиса, предполагая, что, что-то не так. Ф-ия ServiceMain вызывается из SCM когда сервис стартует при загрузке ОС, либо при ручном старте. ServiceMain всегда выполняет следующие шаги:

  1. Немедленный вызов RegisterServiceCtrHandler для регистрации ф-ии Handler в SCM как ф-ии хэндлер процесса.

  2. Затем вызывается SendStatsToSCM. Это оповещает SCM о прогрессе в инициализации сервиса. Четвертый параметр - это значение, которое увеличивается каждый раз, когда программа обновляет статус. SCM и другие программы могут видеть это значение и следить за ходом установки. Последний параметр сообщает SCM как долго (в м.сек.) SCM должен ждать, прежде чем увеличить третий параметр.

  3. Далее генерируется событие, которое может быть использовано в конце ф-ии для предотвращения выхода из нее. Прежде чем это случится, SCM должен выйти по запросу STOP.

  4. Следующим шагом ServiceMain проверяет наличие стартовых параметров, которые пользователь мог задать в Startup Parameters. Параметры обрабатываются в ServiceMain как массив.

  5. Если Вашему сервису требуется инициализация каких-либо задач, то это должно происходить до вызова ф-ии InitService.

  6. Далее стартует InitService, которая запускает трэд с реальной работой сервиса. Если этот вызов происходит успешно, то ServiceMain уведомляет SCM о том, что сервис стартовал удачно.

  7. Запускается функция WaitForSingleObject, которая ждет от Handler появления события terminateEvent. После чего работа функции ServiceMain заканчивается, сервис останавливается.

Как видите, эта функция не слишком гибкая. Исключая шаг №5, Вы обязаны делать все именно так, а не иначе. Вызов в конце функции ServiceMain terminate закрывает все открытые хэндлы и посылает сообщение SCM о том, что сервис остановлен.

SCM вызывает Handler всякий раз, когда нужно поставить на паузу, возобновить выполнение или остановить сервис. Для остановки сервиса Handler устанавливает событие terminateEvent. Делая так, он говорит ServiceMain, запущенной в отдельном трэде, что следует остановиться и закончить свою работу. Прекратив работу ServiceMain Вы останавливаете и сервис. Действие ф-ии SendStatusToSCM заключается в передаче статуса действия сервиса SCM.
 В приведенном примере InitService создает поток сервиса, в нашем случае бесконечный цикл, который "бикает" и "засыпает" на заданные интервалы. Естественно, в своих сервисах Вы поставите здесь свой, более умный код.

Установка и удаление сервиса

Чтобы использовать описанный выше сервис, его необходимо инсталлировать. Инсталляция позволит SCM узнать о сервисе и позволит добавть сервис в общий список сервисов в Service Applet. В листинге №2 показано как это сделать.

Вначале вызывается OpenSCManager, которая устанавливает связь с SCM. В вызове данной ф-ии Вы обязаны указать, что Вы хотите сделать Если у Вас недостаточно полномочий, то SCM вернет Вам NULL.

Вызов CreateService инсталлирует сервис. В качестве параметра используется указатель, возвращенный OpenSCManager, имя, метка для SCM и путь к exe файлу сериса. Использование SERVICE_WIN32_OWN_PROCESS говорит о том, что в exe файле только 1 сервис, а SERVICE_DEMAND_START говорит о том, что данный сервис предпочтительно запускать ручками, а не автоматом. Показано типичное приглашеие для запуска программы установки сервиса:

install BeepService "Beeper" c:\winnt\beep.exe

Первый параметр - имя, используемое внутри SCM. Это же имя используется для удаления сервиса. Второй параметр - метка, видимая в Service Applet. Третий - полный путь к exe файлу сервиса. После установки сервиса запустите его в Service Applet. Если при инсталляции возникли ошибки - смотрите в хэлпе.

В листинге 3 показан процесс удаления сервиса. Открывается соединение с SCM, устанавливается соединение с сервисом посредством OpenService, запрашивается у Handler текущий статус, и, если сервис не остановлен, то останавливает его. Функция DeleteService убирает сервис из Service Applet. Показано типичное приглашеие для запуска программы удаления сервиса:

remove BeepService

Код, реализующий работу простейшего сервиса.
//***************************************************************

// From the book "Win32 System Services: The Heart of Windows NT"

//by Marshall Brain Published by Prentice Hall

// This code implements the simplest possible service.

// It beeps every 2 seconds, or at a user specified interval.

//***************************************************************

// beepserv.cpp

#include

#include

#include

#include

#define DEFAULT_BEEP_DELAY 2000

// Global variables

// The name of the service

char *SERVICE_NAME = "BeepService";

// Event used to hold ServiceMain from completing

HANDLE terminateEvent = NULL;

// Handle used to communicate status info with

// the SCM. Created by RegisterServiceCtrlHandler

SERVICE_STATUS_HANDLE serviceStatusHandle;

// The beep interval in ms.

int beepDelay = DEFAULT_BEEP_DELAY;

// Flags holding current state of service

BOOL pauseService = FALSE;

BOOL runningService = FALSE;

// Thread for the actual work

HANDLE threadHandle = 0;

void ErrorHandler(char *s, DWORD err)

{

cout << s << endl;

cout << "Error number: " << err << endl;

ExitProcess(err);

}

// This function consolidates the activities of

// updating the service status with

// SetServiceStatus

BOOL SendStatusToSCM (DWORD dwCurrentState,

DWORD dwWin32ExitCode,

DWORD dwServiceSpecificExitCode,

DWORD dwCheckPoint,

DWORD dwWaitHint)

{

BOOL success;

SERVICE_STATUS serviceStatus;

// Fill in all of the SERVICE_STATUS fields

serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;

serviceStatus.dwCurrentState = dwCurrentState;

// If in the process of doing something, then accept

// no control events, else accept anything

if (dwCurrentState == SERVICE_START_PENDING)

serviceStatus.dwControlsAccepted = 0;

else

serviceStatus.dwControlsAccepted =

^ SERVICE_ACCEPT_STOP |

SERVICE_ACCEPT_PAUSE_CONTINUE |

SERVICE_ACCEPT_SHUTDOWN;

// if a specific exit code is defined, set up

// the win32 exit code properly

if (dwServiceSpecificExitCode == 0)

serviceStatus.dwWin32ExitCode = dwWin32ExitCode;

else

serviceStatus.dwWin32ExitCode =

ERROR_SERVICE_SPECIFIC_ERROR;

serviceStatus.dwServiceSpecificExitCode =

dwServiceSpecificExitCode;

serviceStatus.dwCheckPoint = dwCheckPoint;

serviceStatus.dwWaitHint = dwWaitHint;

// Pass the status record to the SCM

success = SetServiceStatus (serviceStatusHandle,

&serviceStatus);

return success;

}

DWORD ServiceThread(LPDWORD param)

{

while (1)

{

Beep(200,200);

Sleep(beepDelay);

}

return 0;

}

// Initializes the service by starting its thread

BOOL InitService()

{

DWORD id;

// Start the service's thread

threadHandle = CreateThread(0, 0,

(LPTHREAD_START_ROUTINE) ServiceThread,

0, 0, &id);

if (threadHandle==0)

return FALSE;

else

{

runningService = TRUE;

return TRUE;

}

}

// Dispatches events received from the SCM

VOID Handler (DWORD controlCode)

{

DWORD currentState = 0;

BOOL success;

switch(controlCode)

{

// There is no START option because

// ServiceMain gets called on a start

// Stop the service

case SERVICE_CONTROL_STOP:

// Tell the SCM what's happening

success = SendStatusToSCM(SERVICE_STOP_PENDING,

^ NO_ERROR, 0, 1, 5000);

runningService=FALSE;

// Set the event that is holding ServiceMain

// so that ServiceMain can return

SetEvent(terminateEvent);

return;

// Pause the service

case SERVICE_CONTROL_PAUSE:

if (runningService && !pauseService)

{

// Tell the SCM what's happening

success = SendStatusToSCM(

SERVICE_PAUSE_PENDING,

^ NO_ERROR, 0, 1, 1000);

pauseService = TRUE;

SuspendThread(threadHandle);

currentState = SERVICE_PAUSED;

}

break;

// Resume from a pause

case SERVICE_CONTROL_CONTINUE:

if (runningService && pauseService)

{

// Tell the SCM what's happening

success = SendStatusToSCM(

SERVICE_CONTINUE_PENDING,

^ NO_ERROR, 0, 1, 1000);

pauseService=FALSE;

ResumeThread(threadHandle);

currentState = SERVICE_RUNNING;

}

break;

// Update current status

case SERVICE_CONTROL_INTERROGATE:

// it will fall to bottom and send status

break;

// Do nothing in a shutdown. Could do cleanup

// here but it must be very quick.

case SERVICE_CONTROL_SHUTDOWN:

return;

default:

break;

}

SendStatusToSCM(currentState, NO_ERROR, 0, 0, 0);

}

// Handle an error from ServiceMain by cleaning up

// and telling SCM that the service didn't start.

VOID terminate(DWORD error)

{

// if terminateEvent has been created, close it.

if (terminateEvent) CloseHandle(terminateEvent);

// Send a message to the scm to tell about stopage

if (serviceStatusHandle)

SendStatusToSCM(SERVICE_STOPPED, error,

0, 0, 0);

// If the thread has started, kill it off

if (threadHandle) CloseHandle(threadHandle);

// Do not need to close serviceStatusHandle

}

// ServiceMain is called when the SCM wants to start the service. When it returns,

//the service has stopped. It therefore waits on an event just before the end of the //function, and that event gets set when it is time to stop. It also returns on any error //because the service cannot start if there is an eror.

VOID ServiceMain(DWORD argc, LPTSTR *argv)

{

BOOL success;

// immediately call Registration function

serviceStatusHandle =

RegisterServiceCtrlHandler(

SERVICE_NAME, (LPHANDLER_FUNCTION)Handler);

if (!serviceStatusHandle)

{terminate(GetLastError()); return;}

// Notify SCM of progress

success = SendStatusToSCM(SERVICE_START_PENDING,

^ NO_ERROR, 0, 1, 5000);

if (!success) {terminate(GetLastError()); return;}

// create the termination event

terminateEvent = CreateEvent (0, TRUE, FALSE, 0);

if (!terminateEvent) {terminate(GetLastError()); return;}

// Notify SCM of progress

success = SendStatusToSCM(SERVICE_START_PENDING,

^ NO_ERROR, 0, 2, 1000);

if (!success) {terminate(GetLastError()); return;}

// Check for startup params

if (argc == 2)

{

int temp = atoi(argv[1]);

if (temp < 1000)

beepDelay = DEFAULT_BEEP_DELAY;

else

beepDelay = temp;

}

// Notify SCM of progress

success = SendStatusToSCM(SERVICE_START_PENDING,

^ NO_ERROR, 0, 3, 5000);

if (!success) {terminate(GetLastError()); return;}

// Start the service itself

success = InitService();

if (!success) {terminate(GetLastError()); return;}

// The service is now running.

// Notify SCM of progress

success = SendStatusToSCM(SERVICE_RUNNING,

^ NO_ERROR, 0, 0, 0);

if (!success) {terminate(GetLastError()); return;}

// Wait for stop signal, and then terminate

WaitForSingleObject (terminateEvent, INFINITE);

terminate(0);

}

VOID main(VOID)

{

SERVICE_TABLE_ENTRY serviceTable[] =

{

{ SERVICE_NAME,

(LPSERVICE_MAIN_FUNCTION) ServiceMain},

{ NULL, NULL }

};

BOOL success;

// Register with the SCM

success =

StartServiceCtrlDispatcher(serviceTable);

if (!success)

ErrorHandler("In StartServiceCtrlDispatcher",

GetLastError());

}
Код, реализующий установку сервиса.
//***************************************************************

// From the book "Win32 System Services: The Heart of Windows NT"

// by Marshall Brain

// Published by Prentice Hall

//

// This code installs a service.

//***************************************************************

// install.cpp

#include

#include

void ErrorHandler(char *s, DWORD err)

{

cout << s << endl;

cout << "Error number: " << err << endl;

ExitProcess(err);

}

void main(int argc, char *argv[])

{

SC_HANDLE newService, scm;

if (argc != 4)

{

cout << "Usage:\n";

cout << "install service_name \

service_label executable\n";

cout << "service_name is the \

name used internally by the SCM\n";

cout << "service_label is the \

name that appears in the Services applet\n";

cout << "(for multiple \

words, put them in double quotes)\n";

cout << "executable is the \

full path to the EXE\n\n";

return;

}

// open a connection to the SCM

scm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);

if (!scm) ErrorHandler("In OpenScManager",

GetLastError());

// Install the new service

newService = CreateService(

scm, argv[1], // eg "beep_srv"

argv[2], // eg "Beep Service"

^ SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,

SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,

argv[3], // eg "c:\winnt\xxx.exe"

0, 0, 0, 0, 0);

if (!newService) ErrorHandler("In CreateService",

GetLastError());

else cout << "Service installed\n";

// clean up

CloseServiceHandle(newService);

CloseServiceHandle(scm);

}
Удаление сервиса.

//***************************************************************

// From the book "Win32 System Services: The Heart of Windows NT"

// by Marshall Brain

// Published by Prentice Hall

//

// This code removes a service from the Services applet in the

// Control Panel.

//***************************************************************

// remove.cpp

#include

#include

void ErrorHandler(char *s, DWORD err)

{

cout << s << endl;

cout << "Error number: " << err << endl;

ExitProcess(err);

}

void main(int argc, char *argv[])

{

SC_HANDLE service, scm;

BOOL success;

SERVICE_STATUS status;

if (argc != 2)

{

cout << "Usage:\n remove service_name\n";

return;

}

// Open a connection to the SCM

scm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);

if (!scm) ErrorHandler("In OpenScManager",

GetLastError());

// Get the service's handle

service = OpenService(scm, argv[1],

^ SERVICE_ALL_ACCESS | DELETE);

if (!service) ErrorHandler("In OpenService",

GetLastError());

// Stop the service if necessary

success = QueryServiceStatus(service, &status);

if (!success) ErrorHandler("In QueryServiceStatus",

GetLastError());

if (status.dwCurrentState != SERVICE_STOPPED)

{

cout << "Stopping service...\n";

success = ControlService(service,

SERVICE_CONTROL_STOP, &status);

if (!success) ErrorHandler("In ControlService",

GetLastError());

}

// Remove the service

success = DeleteService(service);

if (success) cout << "Service removed\n";

else ErrorHandler("In DeleteService",

GetLastError());

// Clean up

CloseServiceHandle(service);

CloseServiceHandle(scm);

}

1   2   3   4   5   6   7   8   9   10   11

Похожие:

Методические указания к курсовой работе по дисциплине «Системное программирование и операционные системы» iconМетодические указания к выполнению курсовой работы «Гребные электрические...
Методические указания к выполнению курсовой работы «гребные электрические установки» по дисциплине «электрические системы и комплексы...

Методические указания к курсовой работе по дисциплине «Системное программирование и операционные системы» iconМетодические указания к курсовой работе по курсу "Разведка месторождений полезных ископаемых"
Методические указания к выполнению курсовой работы по дисциплине «Разведка месторождений полезных ископаемых» (для студентов очной...

Методические указания к курсовой работе по дисциплине «Системное программирование и операционные системы» iconМетодические указания к курсовой работе по дисциплине «Теория электрическихцепей»

Методические указания к курсовой работе по дисциплине «Системное программирование и операционные системы» iconМетодические указания и задания к лабораторным работам по курсу «Архитектура компьютеров (АК)»
Методические указания к лабораторным работам по курсу “Архитектура компьютеров предназначены для студентов специальностей «Системное...

Методические указания к курсовой работе по дисциплине «Системное программирование и операционные системы» icon«Системное программирование и операционные системы»
Все цитаты, цифровой, фактический материал и библиографические сведенья проверены, запись единиц соответствует стандартам

Методические указания к курсовой работе по дисциплине «Системное программирование и операционные системы» iconМетодические указания к выполнению курсовой работы по дисциплине «Вычислительный практикум»
Методические указания к выполнению курсовой работы по дисциплине «Вычислительный практикум» для студентов заочной формы обучения...

Методические указания к курсовой работе по дисциплине «Системное программирование и операционные системы» iconМетодические указания к выполнению курсовой работы по дисциплине «Основы маркетинга»
Бобрушева В. В. Методические указания к выполнению курсовой работы по дисциплине «Основы маркетинга» для студентов 2 курса дневной...

Методические указания к курсовой работе по дисциплине «Системное программирование и операционные системы» iconМетодические указания к выполнению лабораторных работ по дисциплине...
Компьютерная инженерия” (для студентов дневной и заочной формы обучения специальности 091501 “Компьютерные системы и сети”, 091502...

Методические указания к курсовой работе по дисциплине «Системное программирование и операционные системы» iconМетодические указания к выполнению курсовой работы по дисциплине...
Методические указания к выполнению курсовой работы по дисциплине «Техническая термодинамика»/ Составители

Методические указания к курсовой работе по дисциплине «Системное программирование и операционные системы» iconМетодические указания к выполнению контрольной работы (ргр) по дисциплине...
Методические указания к выполнению контрольной работы (ргр) по дисциплине «Объектно-ориентированное программирование» (для студентов...

Вы можете разместить ссылку на наш сайт:
Школьные материалы


При копировании материала укажите ссылку © 2013
контакты
uchebilka.ru
Главная страница


<