Поскольку выполнение оболочки, которая поддерживает список задач, может быть прекращено, она использует специфический для каждого пользователя разделяемый файл, в котором содержатся идентификаторы процессов, команды и другая необходимая информация. Благодаря этому перезапуск оболочки никак не отразится на списке задач. В одном из упражнений вам предлагается применять для хранения этой информации не временный файл, а реестр.
Реализация программы наталкивается на определенные проблемы, связанные с параллельным выполнением задач. Некоторые процессы, запущенные из командных строк различных
оболочек, могут одновременно пытаться управлять задачами. Чтобы справиться с этим, функции управления задачами используют блокировки (глава 3) в файле списка задач, в результате чего пользователь может активизировать управление задачами из различных оболочек или процессов.
В полном варианте программы, находящемся на Web-сайте книги, содержится ряд дополнительных возможностей, не представленных в приводимых листингах, например, возможность получения входных данных для командной строки из файла. Программа JobDhell послужит основой для создания более общего "процессора служб" ("service processor") в главе 13 (программа 13.3). Службы NT являются фоновыми процессами, обычно — серверами, управление которыми осуществляется командами запуска, остановки, приостановки, а также другими командами.
Создание фоновых задач
Программа 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(_Т("Управление задачами Windows\n"));
while (!Exit) {
_tprintf(_T("%s"), _T("JM$"));
_fgetts(Command, MAX_COMMAND_LINE, stdin);
pc = strchr(Command, '\n');
*pc = '\0';
/*
Выполнить синтаксический разбор входных данных с целью получения командной строки для новой задачи. */
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) {