Категории
Самые читаемые
💎Читать книги // БЕСПЛАТНО // 📱Online » Компьютеры и Интернет » Программирование » Системное программирование в среде Windows - Джонсон Харт

Читаем без скачивания Системное программирование в среде Windows - Джонсон Харт

Читать онлайн Системное программирование в среде Windows - Джонсон Харт

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 49 50 51 52 53 54 55 56 57 ... 142
Перейти на страницу:

Создание фоновых задач

Программа 6.3 реализует процессор задач, в котором пользователю предлагается ввести одну из трех возможных команд для их дальнейшего выполнения программой. В этой программе используется набор функций управления задачами, представленный программами 6.4, 6.5 и 6.6.

Программа 6.3. JobShell: создание, вывод списка и прекращение выполнения фоновых задач 

/* Глава 6. */

/* JobShell.с – команды управления задачами:

   jobbg — Выполнить задачу в фоновом режиме.

   jobs — Вывести список всех фоновых задач.

   kill — Прекратить выполнение указанной задачи из семейства задач.

   Существует опция, позволяющая генерировать управляющие сигналы консоли. */

#include "EvryThng.h"

#include "JobMgt.h"

int _tmain(int argc, LPTSTR argv[]) {

 BOOL Exit = FALSE;

 TCHAR Command[MAX_COMMAND_LINE + 10], *pc;

 DWORD i, LocArgc; /* Локальный параметр argc. */

 TCHAR argstr[MAX_ARG][MAX_COMMAND_LINE];

 LPTSTR pArgs[MAX_ARG];

 for (i = 0; i < MAX_ARG; i++) pArgs[i] = argstr[i];

 /* Вывести подсказку пользователю, считать команду и выполнить ее. */

 _tprintf(_Т("Управление задачами Windowsn"));

 while (!Exit) {

  _tprintf(_T("%s"), _T("JM$"));

  _fgetts(Command, MAX_COMMAND_LINE, stdin);

  pc = strchr(Command, 'n');

  *pc = '';

  /* Выполнить синтаксический разбор входных данных с целью получения командной строки для новой задачи. */

  GetArgs(Command, &LocArgc, pArgs); /* См. Приложение А. */

  CharLower(argstr[0]);

  if(_tcscmp(argstr[0], _T("jobbg")) == 0) {

   Jobbg(LocArgc, pArgs, Command);

  } else if(_tcscmp(argstr[0], _T("jobs")) == 0) {

   Jobs(LocArgc, pArgs, Command);

  } else if(_tcscmp(argstr[0], _T("kill")) == 0) {

   Kill(LocArgc, pArgs, Command);

  } else if(_tcscmp(argstr[0], _T("quit")) == 0) {

   Exit = TRUE;

  } else _tprintf(_T("Такой команды не существует. Повторите вводn"));

 }

 return 0;

}

/* jobbg [параметры] командная строка [Параметры являются взаимоисключающими]

 –с: Предоставить консоль новому процессу.

 -d: Отсоединить новый процесс без предоставления ему консоли.

 Если параметры не заданы, процесс разделяет консоль с jobbg. */

int Jobbg(int argc, LPTSTR argv[], LPTSTR Command) {

 DWORD fCreate;

 LONG JobNo;

 BOOL Flags[2];

 STARTUPINFO Startup;

 PROCESS_INFORMATION ProcessInfo;

 LPTSTR targv = SkipArg(Command);

 GetStartupInfo(&StartUp);

 Options(argc, argv, _T("cd"), &Flags[0], &Flags[1], NULL);

 /* Пропустить также поле параметра, если он присутствует. */

 if (argv[1][0] == '-') targv = SkipArg(targv);

 fCreate = Flags[0] ? CREATE_NEW_CONSOLE : Flags [1] ? DETACHED_PROCESS : 0;

 /* Создать приостановленную задачу/поток. Возобновить выполнение после ввода номера задачи. */

 CreateProcess(NULL, targv, NULL, NULL, TRUE, fCreate | CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP, NULL, NULL, &StartUp, &ProcessInfo);

 /* Создать номер задачи и ввести ID и дескриптор процесса в "базу данных" задачи. */

 JobNo = GetJobNumber(&ProcessInfo, targv); /* См. "JobMgt.h" */

 if (JobNo >= 0) ResumeThread(ProcessInfo.hThread);

 else {

  TerminateProcess(ProcessInfo.hProcess, 3);

  CloseHandle(ProcessInfo.hProcess);

  ReportError(_T("Ошибка: Не хватает места в списке задач."), 0, FALSE);

  return 5;

 }

 CloseHandle(ProcessInfo.hThread);

 CloseHandle(ProcessInfo.hProcess);

 _tprintf(_T(" [%d] %dn"), JobNo, ProcessInfo.dwProcessId);

 return 0;

}

/* jobs: вывод списка всех выполняющихся и остановленных задач. */

int Jobs(int argc, LPTSTR argv[], LPTSTR Command) {

 if (!DisplayJobs ()) return 1; /*См. описание функций управления задачами*/

 return 0;

}

/* kill [параметры] Номер задачи (JobNumber)

 –b: Генерировать Ctrl-Break.

 –с: Генерировать Ctrl-C.

 В противном случае прекратить выполнение процесса. */

int Kill(int argc, LPTSTR argv[], LPTSTR Command) {

 DWORD ProcessId, JobNumber, iJobNo;

 HANDLE hProcess;

 BOOL CntrlC, CntrlB, Killed;

 iJobNo = Options(argc, argv, _T("bc"), &CntrlB, &CntrlC, NULL);

 /* Найти ID процесса, связанного с данной задачей. */

 JobNumber = _ttoi(argv [iJobNo]);

 ProcessId = FindProcessId(JobNumber); /* См. описание функций управления задачами. */

 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);

 if (hProcess == NULL) { /* ID процесса может не использоваться. */

  ReportError(_T("Выполнение процесса уже прекращено.n"), 0, FALSE);

  return 2;

 }

 if (CntrlB) GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, ProcessId);

 else if (CntrlC) GenerateConsoleCtrlEvent(CTRL_C_EVENT, ProcessId);

 else TerminateProcess(hProcess, JM_EXIT_CODE);

 WaitForSingleObject(hProcess, 5000);

 CloseHandle(hProcess);

 _tprintf(T("Задача [%d] прекращена или приостановлена n"), JobNumber);

 return 0;

Обратите внимание на то, как команда jobbg создает процесс в приостановленном состоянии, а затем вызывает функцию управления задачами Get JobNumber (программа 6.4) для получения номера задачи, а также регистрации задачи и процесса, который с ней связан. Если в силу каких-либо причин задача не может быть зарегистрирована, выполнение данного процесса немедленно прекращается. Обычно' генерируется корректный номер задачи, после чего выполнение основного потока возобновляется, и он может продолжать выполнение.

Получение номера задачи

Следующие три программы представляют три отдельные функции управления задачами. Все эти функции включены в единый файл JobMgt.c, содержащий все исходные тексты.

Первая из них, программа 6.4, представляет функцию Get JobNumber. Обратите внимание на использование блокирования файлов, а также обработчиков завершения, осуществляющих разблокирование файлов. Эта методика обеспечивает защиту от исключений и непреднамеренного обхода вызова функции разблокирования файлов. Переходы такого рода могут быть случайно вставлены в процессе сопровождения кода, даже если исходная программа корректна. Обратите также внимание на блокирование попыток записи за пределами конца файла в тех случаях, когда файл должен быть расширен за счет добавления новой записи.

Программа 6.4. JobMgt: создание информации о новой задаче 

/* Вспомогательная функция управления задачами. */

#include "EvryThng.h"

#include "JobMgt.h" /* Листинг приведен в приложении А. */

void GetJobMgtFileName (LPTSTR);

LONG GetJobNumber(PROCESS_INFORMATION *pProcessInfo, LPCTSTR Command)

/* Создать номер задачи для нового процесса и ввести информацию о новом процессе в базу данных задачи. */

{

 HANDLE hJobData, hProcess;

 JM_JOB JobRecord;

 DWORD JobNumber = 0, nXfer, ExitCode, FsLow, FsHigh;

 TCHAR JobMgtFileName[MAX_PATH];

 OVERLAPPED RegionStart;

 if (!GetJobMgtFileName(JobMgtFileName)) return –1;

 /* Предоставление результата в виде строки "tmpUserName.JobMgt" */

 hJobData = CreateFile(JobMgtFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

 if (hJobData == INVALID_HANDLE_VALUE) return –1;

 /* Блокировать весь файл плюс одну возможную запись для получения исключительного доступа. */

 RegionStart.Offset = 0;

 RegionStart.OffsetHigh = 0;

 RegionStart.hEvent = (HANDLE)0;

 FsLow = GetFileSize(hJobData, &FsHigh);

 LockFileEx(hJobData, LOCKFILE_EXCLUSIVE_LOCK, 0, FsLow + SJM_JOB, 0, &RegionStart);

 __try {

  /* Чтение записи для нахождения пустого сегмента. */

  while(ReadFile(hJobData, &JobRecord, SJM_JOB, &nXfer, NULL) && (nXfer > 0)) {

   if (JobRecord.ProcessId == 0) break;

   hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, JobRecord.ProcessId);

   if (hProcess == NULL) break;

   if (GetExitCodeProcess(hProcess, &ExitCode) && (ExitCode != STILL_ACTIVE)) break;

   JobNumber++;

  } 

  /* Либо найден пустой сегмент, либо мы находимся в конце файла и должны создать новый сегмент. */

  if (nXfer != 0) /* Не конец файла. Резервировать. */

   SetFilePointer(hJobData, –(LONG)SJM_JOB, NULL, FILE_CURRENT);

  JobRecord.ProcessId = pProcessInfo->dwProcessId;

  _tcsnccpy(JobRecord.CommandLine, Command, MAX_PATH);

  WriteFile(hJobData, &JobRecord, SJM_JOB, &nXfer, NULL);

 } /* Конец try-блока. */

 __finally {

  UnlockFileEx(hJobData, 0, FsLow + SJM_JOB, 0, &RegionStart);

  CloseHandle(hJobData);

 }

 return JobNumber + 1;

}

Вывод списка фоновых задач

Программа 6.5 реализует функцию управления задачами DisplayJobs.

Программа 6.5. JobMgt: отображение списка активных задач 

BOOL DisplayJobs(void)

/* Просмотреть файл базы данных, сообщить статус задачи. */

{

 HANDLE hJobData, hProcess;

 JM_JOB JobRecord;

 DWORD JobNumber = 0, nXfer, ExitCode, FsLow, FsHigh;

1 ... 49 50 51 52 53 54 55 56 57 ... 142
Перейти на страницу:
На этой странице вы можете бесплатно скачать Системное программирование в среде Windows - Джонсон Харт торрент бесплатно.
Комментарии