Книга: Системное программирование в среде Windows

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

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

Программа 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) для получения номера задачи, а также регистрации задачи и процесса, который с ней связан. Если в силу каких-либо причин задача не может быть зарегистрирована, выполнение данного процесса немедленно прекращается. Обычно' генерируется корректный номер задачи, после чего выполнение основного потока возобновляется, и он может продолжать выполнение.

Оглавление книги


Генерация: 1.678. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз