Джонсон Харт - Системное программирование в среде Windows
- Название:Системное программирование в среде Windows
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2005
- Город:Москва • Санкт-Петербург • Киев
- ISBN:5-8459-0879-5
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Джонсон Харт - Системное программирование в среде Windows краткое содержание
Эта книга посвящена вопросам разработки приложений с использованием интерфейса прикладного программирования операционных систем компании Microsoft (Windows 9х, Windows XP, Windows 2000 и Windows Server 2003). Основное внимание уделяется базовым системным службам, включая управление файловой системой, процессами и потоками, взаимодействие между процессами, сетевое программирование и синхронизацию. Рассматривается методика переноса приложений, написанных в среде Win32, в среду Win64. Подробно описываются все аспекты системы безопасности Windows и ее практического применения. Изобилие реальных примеров, доступных также и на Web-сайте книги, существенно упрощает усвоение материала.
Книга ориентирована на разработчиков и программистов, как высокой квалификации, так и начинающих, а также будет полезна для студентов соответствующих специальностей.
Системное программирование в среде Windows - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Получение номера задачи
Следующие три программы представляют три отдельные функции управления задачами. Все эти функции включены в единый файл JobMgt.c, содержащий все исходные тексты.
Первая из них, программа 6.4, представляет функцию Get JobNumber. Обратите внимание на использование блокирования файлов, а также обработчиков завершения, осуществляющих разблокирование файлов. Эта методика обеспечивает защиту от исключений и непреднамеренного обхода вызова функции разблокирования файлов. Переходы такого рода могут быть случайно вставлены в процессе сопровождения кода, даже если исходная программа корректна. Обратите также внимание на блокирование попыток записи за пределами конца файла в тех случаях, когда файл должен быть расширен за счет добавления новой записи.
/* Вспомогательная функция управления задачами. */
#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;
/* Предоставление результата в виде строки "\tmp\UserName.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.
BOOL DisplayJobs(void)
/* Просмотреть файл базы данных, сообщить статус задачи. */
{
HANDLE hJobData, hProcess;
JM_JOB JobRecord;
DWORD JobNumber = 0, nXfer, ExitCode, FsLow, FsHigh;
TCHAR JobMgtFileName[MAX_PATH];
OVERLAPPED RegionStart;
GetJobMgtFileName(JobMgtFileName);
hJobData = CreateFile(JobMgtFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
RegionStart.Offset = 0;
RegionStart.OffsetHigh = 0;
RegionStart.hEvent = (HANDLE)0;
FsLow = GetFileSize(hJobData, &FsHigh);
LockFileEx(hJobData, LOCKFILE_EXCLUSIVE_LOCK, 0, FsLow, FsHigh, &RegionStart);
__try {
while(ReadFile(hJobData, &JobRecord, SJM_JOB, &nXfer, NULL) && (nXfer > 0)) {
JobNumber++;
if (JobRecord.ProcessId == 0) continue;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, JobRecord.ProcessId);
if (hProcess != NULL) GetExitCodeProcess(hProcess, &ExitCode);
_tprintf(_T(" [%d] "), JobNumber);
if (hProcess == NULL) _tprintf(_T(" Готово"));
else if (ExitCode != STILL_ACTIVE) _tprintf(_T("+ Готово"));
else _tprintf(_T(" "));
_tprintf(_T(" %s\n"), JobRecord.CommandLine);
/* Удалить процессы, которые в системе уже не присутствуют. */
if (hProcess == NULL) {
/* Зарезервировать одну запись. */
SetFilePointer(hJobData, –(LONG)nXfer, NULL, FILE_CURRENT);
JobRecord.ProcessId = 0;
WriteFile(hJobData, &JobRecord, SJM_JOB, &nXfer, NULL);
}
} /* Конец цикла while. */
} /* Конец __try-блока. */
__finally {
UnlockFileEx(hJobData, 0, FsLow, FsHigh, &RegionStart);
CloseHandle(hJobData);
}
return TRUE;
}
Поиск задачи в файле списка задач
Программа 6.6 представляет последнюю функцию управления задачами, FindProcessID, которая получает идентификатор процесса, соответствующего задаче с указанным номером. В свою очередь, идентификатор процесса может использоваться вызывающей программой для получения дескриптора и другой информации о состоянии процесса.
DWORD FindProcessId(DWORD JobNumber)
/* Получить ID процесса для задачи с указанным номером. */
{
HANDLE hJobData;
JM_JOB JobRecord;
DWORD nXfer;
TCHAR JobMgtFileName[MAX_PATH];
OVERLAPPED RegionStart;
/* Открыть файл управления задачами. */
GetJobMgtFileName(JobMgtFileName);
hJobData = CreateFile(JobMgtFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hJobData == INVALID_HANDLE_VALUE) return 0;
/* Перейти к позиции записи, соответствующей указанному номеру задачи.
* В полной версии программы обеспечивается принадлежность номера задачи (JobNumber) допустимому диапазону значений. */
SetFilePointer(hJobData, SJM_JOB * (JobNumber – 1), NULL, FILE_BEGIN);
/* Блокировка и чтение записи. */
RegionStart.Offset = SJM_JOB * (JobNumber – 1);
RegionStart.OffsetHigh =0; /* Предполагаем, что файл "короткий". */
RegionStart.hEvent = (HANDLE)0;
LockFileEx(hJobData, 0, 0, SJM_JOB,0, &RegionStart);
ReadFile(hJobData, &JobRecord, SJM_JOB, &nXfer, NULL);
UnlockFileEx(hJobData, 0, SJM_JOB, 0, &RegionStart);
CloseHandle(hJobData);
return JobRecord.ProcessId;
}
Объекты задач
Процессы можно объединять в объекты задач (job objects), что позволяет управлять процессами как группой, устанавливать лимиты ресурсов для всех процессов, входящих в объект задачи, и вести учетную информацию. Объекты задач были впервые введены в Windows 2000 и теперь поддерживаются во всех системах NT5.
Первым шагом является создание пустого объекта задачи с помощью функции CreateObject, которая принимает два аргумента, имя и атрибуты защиты, и возвращает дескриптор объекта задачи. Существует также функция OpenJobObject, которую можно применять к именованным объектам задач. Для уничтожения объектов используется функция CloseHandle.
Функция AssignProcessToJobObject просто добавляет процесс с указанным дескриптором в объект задачи; она принимает только два параметра. Процесс может принадлежать только одной задаче, поэтому в тех случаях, когда процесс, связанный с указанным дескриптором, уже является элементом какого-либо задания, функция AssignProcessToJobObject завершается с ошибкой. Добавляемый в задачу процесс наследует значения всех ограничений, связанных с задачей, и добавляет в задачу свою учетную информацию, например использованное процессорное время.
Читать дальшеИнтервал:
Закладка: