/
Tags: операційні системи лабораторна робота
Year: 2015
Similar
Text
1.
ПРОЦЕСИ, НИТКИ, ВОЛО
КНА ТА
ЗАВДАННЯ
Мета
:
вивчити можливості по створенню, керуванню виконанням
та завершенню процесів, ниток, волокон та
завдань
в операційній си
с-
темі
(ОС)
Windows.
1.1.
Теоретичні відомості
В
ОС
Windows підтримуються процеси, що скла
даються
з
декіл
ь-
кох ниток.
Процес
–
це об’єкт ядра, який має в своєму розпорядженні
д
е
який набір ресурсів.
Нитка
(також об’єкт ядра)
–
незалежн
а частина
проц
е
су, що
викон
ується, при цьому вона
розділяє з процесом спільний
адресний про
с
тір, код та змінні.
В
олокно
–
спрощена нитка, виконання
якої планується в програмі вручну.
Завдання
–
об’єкти ядра
, що вик
о-
нують роль контейнерів процесів. Розглянемо ці об’єкти д
о
кладніше.
1.1.1.
Процеси
Процесом зазвичай називають екземпляр
програми, що
викону
єт
ь-
ся
.
В деяки
х джерелах інформації не розрізнюють поняття
програм
и
і
процес
у
,
а
ле
вони фундаментально відрізняються один від одного. Пр
о-
грама є ст
а
тичним набором команд, а процес
–
це набір ресурсів і даних,
що викори
с
товуються при виконанні програми. Процес
(Process)
у
Windows складаєт
ь
ся з
таких
компонентів:
▪
с
труктура даних, що містить у
сю інформацію про процес, у тому
числі список відкритих дескрипторів різних системних ресурсів, унік
а-
льний ідентифікатор процесу, рі
зну статистичну інформацію і т.
ін
.;
▪
а
дресний пр
остір
–
діапазон адрес віртуальної пам'яті, яким може
к
о
ристуватися процес;
▪
в
иконувана програма і дані, що проектуються на віртуальний а
д-
ре
с
ний простір процесу.
Створення
процесу в системі
Win32
здійснюється завдяки виклику
о
д
нієї з таких функцій, як
Cre
ateProcess
,
CreateProcessAsUser
(для ОС
WinNT/2000) або
CreateProcessWithLogonW
(починаючи з ОС
Win2000), і
виконується
в декілька етапів:
▪
Відкривається файл образу (EXE файл), який буде виконуватись
у
процесі. Якщо виконуваний файл не є Win32 прикладною
програмою,
то відбувається пошук образу підтримки (support image) для запуску цієї
пр
о
грами. Наприклад, якщо виконується файл з розширенням .bat, то
запуск
а
ється командний процесор, а саме програма cmd.exe
. Примітка
:
В ОС WinNT/2000 реалізований
такий
мех
анізм для
завантаження
пр
о-
грам: фу
н
кція
CreateProcess
після того, як знайде виконуваний Win32
файл, шукає в системному реєстрі
за маршрутом
HKEY_LOCAL
-
MACHINE
\
SOFTWARE
\
Microsoft
\
WindowsNT
\
CurrentVersion
\
Image
File
Execution
Option
розділ з ім’ям і
розширенням файл
а
, який
запускається. Потім в ньому вказана фун
к
ція шукає параметр
Debugger
і, якщо рядок не пустий, запускає те, що в ньому записане, замість даної
пр
о
грами.
▪
Створюється об’єкт ядра „п
роцес
”
.
▪
Створюється первинна нитка
(стек, контекст
і об’єкт ядра „
ни
т-
ка
”
).
▪
Підсистема Win32 сповіщається про створення нових процесу і
ни
т
ки.
▪
Починається виконання первинної нитки.
▪
В контексті нового процесу і нитки ініціалізується адресний пр
о-
стір (наприклад, завантажуються необхідні DLL бібліотеки)
і почин
а-
ється в
и
конання програми.
Параметри виклику функції
CreateProcess
:
BOOL CreateProcess
(
LPCTSTR lpApplicationName,
//
ім’я файл
а
-
прогр
а
м
и
LPTSTR lpCommandLine,
//
командний рядок викл
и
ку
LPSECURITY_ATTRIBUTES lpProcessAttributes,
//
покажчи
к
на структуру атрибутів захисту
пр
оцесу
LPSECURITY_ATTRIBUTES lpThreadAttributes,
//
пока
ж
чик
на структуру атрибутів захисту нитки
BOOL bInheritHandles,
//
ознака наслідування
//
дескри
п
торів процесу, що викликав функцію
DWORD dwCreationFlags, //
пр
апорці створення
//
проц
е
су та призначення йому пріоритету
LPVOID lpEnvironment,
//
покажчик на змінні
//
серед
о
вища
LPCTSTR lpCurrentDirectory, //
ім’я поточного
//
кат
а
логу
LPSTARTUPINFO lpStar
tupInfo, //
покажчик на
//
структ
у
ру з параметрами вікна
LPPROCESS_INFORMATION lpProcessInformation
/
/
покажчик на структуру з даними про створений
//
пр
о
цес
);
Функція
CreateProcessAsUser
та
CreateProcessWithLogonW
д
о-
зволя
ють
створити процес
у
контексті захисту користувача,
це
задає
ться
о
д
ним з параметрів виклику. Функція
CreateProcessAsUser
потребує
виклику функції входу
користувача
до системи
LogonUser
.
Процес завершується
,
якщо:
▪
Вхідна функція первинної нитки повернула управління.
▪
Одна з ниток процесу викликала функцію
ExitPro
cess
.
▪
Нитка іншого процесу викликала функцію
TerminateProcess
.
Коли процес завершується, всі User
-
і GDI
-
об’єкти,
що були
ств
о-
рені процесом, знищуються, об’єкти ядра закриваються (якщо їх не в
и-
корист
о
вує інший процес), адресний простір процесу
також
знищ
ується.
Параметри виклику вказаних функцій:
VOID ExitProcess
(
UINT uExitCode
//
код виход
у
для всіх ниток
);
// п
роц
е
су
BOOL TerminateProcess(
HANDLE hProcess, //
дескриптор процесу
UINT uExitCode //
код виход
у
для процесу
);
Приклад
:
п
рограм
а створює процес
„
Калькулятор
”
.
Примітка
: при створенні процесу функцією
CreateProcess
пар
а-
метр
lpCommandLine
повинен
містити адресу рядка символів, а не кон
с-
танту (при виконанні функції командний рядок виклику процесу змін
ю-
ється, а при виході з функції
–
відно
в
люється).
#include <windows.h>
int main
(int argc, char* argv[])
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
LPTSTR lpszSystemInfo;
TCHAR tchBuff[MAX_PATH+1];
lpszSystemInfo = tchBuff;
GetSystemDirector
y (lpszSystemInfo,MAX_PATH+1);
wsprintf(t
chBuff,"%s
\
\
calc.exe",lpszSystemInfo);
ZeroMemory
(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
if
(!CreateProcess
(NULL,
tchBuff,
NULL,
NULL,
FALSE,0, NULL, NULL, &si, &pi))
return 0;
//
Закриття дескриптора
CloseHandle
( pi.hProcess );
// процесу
CloseHandle( pi.hThread );
// та основної нитки
return 0;
}
1.1.2.
Нитки
Кожна нитка має:
▪
унікальний ідентифікатор нитки;
▪
вміст сукупності регістрів процесора, що відображають стан пр
о-
цесора
взагалі
;
▪
два стека, один з
як
их
використовується ниткою при її виконанні
в режимі ядра, а
другий
–
в режимі
користувача
;
▪
закриту область пам’яті,
що
називається локальною пам’яттю н
и-
тки (TLS
–
T
hread
L
ocal
S
torage) і яку використовують підсистеми ОС,
run
-
time бібліотеки та DLL бібл
іотеки (Dynamic Link Library).
Щоб усі нитки, створені у системі, виконувались,
ОС
відводить
кожній з них визначений інтервал процесорного часу.
Тим самим ств
о-
рюється ілюзія одночасного виконання ниток (зрозуміло, що для баг
а-
топроц
е
сорних комп’ютерів можли
вий дійсний паралелізм). В ОС
Windows реалізована система планування
з витісненням
на основі прі
о-
ритетів, в якій завжди в
и
конується нитка
, що готова до виконання та
має
найбільши
й
пріор
и
тет.
О
брана для виконання нитка виконується
протя
гом
де
як
ого проміжку
часу,
що
називається
квантом
. Квант в
и-
значає, скільки часу буде в
и
конуватись нитка, поки
ОС
не перерве її
виконання. По закінченні кванта
ОС
перев
і
ряє, чи готова до виконання
інша нитка з таким же (або більшим) рівнем пріоритету. Якщо такі ни
т-
ки не виявлен
і, поточній нитці виділяється ще один квант. З іншого б
о-
ку
,
нитка може не повністю використати свій квант. Як тільки інша ни
т-
ка з більш високим пріоритетом стане готовою до вик
о
нання, поточна
нитка витісняється, навіть якщо її квант ще не виче
р
паний.
Квант
не вимірюється в одиницях часу, він виражається цілим чи
с-
лом. Для кожної нитки зберігається поточне значення її кванта. Коли
нитці в
и
діляється квант процесорного часу, це означає, що її квант
установлюється в початкове значення. Воно залежить від
ОС
. Напр
и-
клад, для Win
dows
2000 Professional початкове значення кванта дорі
в-
нює 6, а для
Windows
2000 Server
–
36.
Кож
ного
раз
у
, коли виникає переривання від таймера, із кванта н
и-
тки віднімається число 3, і так доти, поки він не досягне нульового зн
а-
чення. Частота
спрацьовування таймера залежить від апаратної платф
о-
рми. Наприклад, для більшості однопроцесорних x86 систем вона ст
а-
новить 10
мс, а
для
більшості багатопроцесорних x86 систем
–
15
мс.
У будь
-
якому випадку
ОС
повинна визначити, яку нитку виконув
а-
ти наступ
ною.
О
бравши нову нитку,
ОС
переключає контекст. Ця оп
е-
рація полягає в тому, що зберігаються параметри нитки, яка щойно в
и-
конувалась (регістри процесора, покажчики на стеки ядра і користува
ча
,
покажчик на адресний прост
ір, у
якому виконувалась вказана нитк
а
,
та
інш
е
), і завант
а
жуються аналогічні параметри для другої нитки. Після
цього починається в
и
конання нової нитки.
Планування в ОС Windows здійснюється на рівні ниток, а не пр
о-
цесів. Це зрозуміло, тому що самі процеси не виконуються, а лише в
и-
діляють р
е
су
рси і контекст для виконання ниток. Тому при плануванні
ниток система не звертає уваг
и
на те, якому процесу вони належать. Н
а-
приклад, я
к
що процес А має 10 готових до виконання ни
ток, а процес Б
–
дві, і всі 12
ниток мають однаковий пріоритет, то кожна з ни
х отримає
1/12 проц
е
сорного часу.
В ОС Windows існує 32 рівня
пріоритету
–
від 0 до 31. Вони гр
у-
пуються так: 31
–
16
–
рівні реального часу; 15
–
1
–
динамічні рівні; 0
–
систе
м
ний рівень,
що
зарезервований для
процесу
обнуління
сторінок
(zero
-
page thread).
Пр
іоритет кожної нитки (базовий пріоритет нитки) складається із
пріоритету її процесу і відносного пріоритету самої нитки. Є сім відно
с-
них прі
о
ритетів ниток:
▪
n
ormal
–
такий же, як і у
процесу
;
▪
a
bove normal
–
+1 до пріоритету процесу;
▪
b
elow normal
–
–
1;
▪
h
ighest
–
+2;
▪
l
owest
–
–
2;
▪
t
ime critical
–
встановлює числове значення базового пріоритету
ни
т
ки
для Real time класу в 31, для решти класів
–
в 15;
▪
i
dle
–
встановлює числове значення базового пріоритету
нитики
для Real time класу в 16, для решти к
ласів
–
в 1.
Якщо
ОС
функціонує на машині, де розміщено більше одного пр
о-
цесора, то, за замовчуванням, нитка виконується на будь
-
якому досту
п-
ному процесорі. Але в деяких випадках набір процесорів, на яких нитка
може виконуватись, може бути обмеженим. Цю си
туацію називають
прив’язкою до процесорів (processor affinity). Можна змінити прив’язку
до процесорів програмно, через Win32
-
функції планування
SetProcessAffinityMask
,
SetThreadAffinityMask
(прив’язування проц
е-
су та нитки до конкре
т
ного процесор
а
) та
SetTh
readIdealProcessor
(встановлення бажаного процесор
а
нитки)
.
Для роботи з нитками використовуються
такі
функції
(перерахов
а-
ні найбільш часто
використовувані
)
:
CreateRemoteThread
(створення
нитки в адресному просторі іншого процесу),
CreateThread
(створення
нитки в адресному просторі поточного процесу),
ExitThread
(заве
р-
шення роботи поточної нитки
)
,
GetCurrentThread
(отримання псевд
о-
дескриптора поточної нитки),
GetCurrentThreadId
(отримання ідент
и-
фікатор
а
поточної нитки),
GetExitCodeThread
(отримання коду зав
е
р-
шення нитки),
ResumeThread
(зменшення лічильник
а
зупинки нитки,
коли дорівнює 0
–
нитка продовжує виконання),
SuspendThread
(збіл
ь-
шення лічильнику з
у
пинки нитки, коли більше 0
–
виконання нитки
призупиняється),
SwitchToThread
(
звільнення процесор
а від ви
конання
поточно
ї
нитк
и
та
переключення
на іншу
),
TerminateThread
(примус
о-
ве завершення нитки).
Для створення нитки
в адресному просторі пот
о-
чного процесу
в фун
к
ції використовуються
такі
параметри:
HANDLE CreateThread
(
LPSECURITY_ATTRIBUTES lpThreadAttri
butes,
//
пока
ж
чик
на структуру атрибутів захисту
SIZE_T dwStackSize
, //
розмір стек
а
для нитки,
//
0
–
задати розмір стека
як у основної ни
т
ки
LPTHREAD_START_ROUTINE lpStartAddress,
//
покажчик на
функцію нитки
LPVOID lpParameter,
//
параметр, що
передається
//
ни
т
ці
DWORD dwCreationFlags,
//
параметр створення, якщо
//
він
містить CREATE_SUSPENDED
–
нитка
//
створюється
в
приз
у
пиненому
стані
LPDWORD lpThreadId
//
ідентифікатор нит
к
и, для
//
Windows NT/2000 та вище
–
може бути NULL
);
1.1.
3
.
Волокна
Волокна підтримуються в WIN32 API починаючи з Windows
2000.
Як було сказано вище: в
олокно
–
це спрощена нитка, виконання якої
планується самою прикладною програмою, а не планувальником проц
е-
сорного часу
ОС
. Планування волокон може здійс
нюватись шляхом п
е-
реключення на них тільки з
інших
волокон. Волокна виконуються в
контексті ниток, в яких планується їх використання, і допускають повну
їх ідентифікацію з нитками. В кожній нитці може бути заплановано д
е-
кілька волокон. Для кожного волокна
створюється власний стек, в як
о-
му зберігається інформ
а
ція про стан волокна.
Волокно може бути створене за допомогою
функції
CreateFiber
із
о
с
новної нитки процесу або отримане шляхом перетворення
на
волокно
поточної нитки за допомогою функції
ConvertThreadT
oFiber
. Пер
е-
ключення поміж волокнами може бути організоване за допомогою фу
н-
кції
SwitchToFiber
, але її в
и
клик можна здійснювати тільки із волокна.
Пар
аметри вказаних функцій
:
LPVOID CreateFiber
(
SIZE_T dwStackSize, //
розмір стек
а
для волокна,
//
0
–
з
адати розмір стек
а
як у основної ни
т
ки
LPFIBER_START_ROUTINE lpStartAddress, //
покажчик
//
на
функцію воло
к
на
LPVOID lpParameter //
параметр, що передається
//
вол
о
кну
);
LPVOID ConvertThreadToFiber
(
LPVOID lpParameter //
параметр, що п
ередає
ться
//
вол
о
кну
);
VOID SwitchToFiber
(
LPVOID lpFiber //
адреса волокна, яке запускаєт
ь
ся
);
Для отримання параметру, що передається в волокно, використов
у-
єт
ь
ся функція
GetFiberData
.
Для зворотного перетворення волокна на
нитку використовує
ться функція
ConvertFiberToThread
.
Приклад.
Програма створює
чотири
волокна, кожне з яких виконує
п
е
реключення на наступне волокно. Якщо число переключень більше
10, робота
пр
о
грами
завершується.
//
задамо мінімальну версію
ОС
–
Wi
n
dows 2000
#define _WIN
32_WINNT 0x0500
#define WINVER 0x0500
#include <windows.h>
#include <stdio.h>
#include <conio.h>
int Counter;
void *fiber[5];
void WINAPI Func(void *)
{
for
(;;) {
printf
("Fiber Number %d
\
n",Counter%4);
getch();
if ((Counter++)<10) {
SwitchToFiber
(fiber[Counter%4]);
} else break;
}
}
int main(int argc, char* argv[])
{
Counter
=
0;
fiber[0]
=
CreateFiber
(0,Func,NULL);
fiber[1]
=
CreateFiber
(0,Func,NULL);
fiber[2]
=
CreateFiber
(0,Func,NULL);
fiber[3]
=
CreateFiber
(0,Func,NULL);
//
для
перемикання на
пер
ше
волокно необх
і
д
н
о
//
перетв
о
рити поточну
нит
ку
на
волокно
fiber[4]
=
ConvertThreadToFiber
(NULL);
SwitchToFiber
(fiber[0]);
return 0;
}
Для примусового знищення волокон застосовується функція
DeleteFiber
. Також для знищення волоко
н можуть бути використані всі
функції, які призначені для знищення ниток.
Параметри функції зн
и-
щення
волокн
а
:
VOID DeleteFiber
(
LPVOID lpFiber
//
покажчик на волокно для знище
н
ня
);
1.1.4.
Функції очікування
П
ризупиня
ти
виконання нитки можна
різними
за
соб
ами
.
Функція
Sleep
призупиняє виконання нитки на задане число м
і-
лісекунд. Якщо
я
к аргумент даної функції вказати 0, то
н
итка відм
о-
виться від свого кванта процесорного часу, але негайно з’явиться в сп
и-
ску ниток, готових до виконання. Іншими словами, відб
удеться навми
с-
не переключення ниток (
правильніше
, спроба переключення
–
адже н
а-
ступною для виконання ниткою цілком імовірно може ст
а
ти та ж сама).
Приклад.
Програма створює процес
„
Калькулятор
”
і через 15 с
е-
кунд його знищує.
#include <windows.h>
int main
(int argc, char* argv[])
{
STARTUPINFO StartUpInfo;
PROCESS_INFORMATION ProcessInfo;
LPTSTR lpszSystemInfo;
TCHAR tchBuff[MAX_PATH+1];
lpszSystemInfo = tchBuff;
GetSystemDirectory(lpszSystemInfo,MAX_PATH+1);
wsprintf(tchBuff,"%s
\
\
calc.exe",lpszSyste
mInfo);
memset(&StartUpInfo,0,sizeof(STARTUPINFO));
StartUpInfo.cb
=
sizeof(STARTUPINFO);
if (CreateProcess
(NULL,
lpszSystemInfo,
NULL,
NULL,
FALSE,NORMAL_PRIORITY_CLASS,NULL,
NULL,&StartUpInfo,&ProcessInfo))
{
Sleep
(15000);
TerminateProcess
(ProcessInfo.hProcess,
0);
}
ExitProcess
(0);
}
Функція
WaitForSingleObject
призупиняє виконання нитки до тих
пір, поки не відбудеться одна із двох подій:
▪
закінчиться
час
очікування;
▪
очікуваний об’єкт перейде в сигнальний
(signaled
) стан.
За значен
ням, яке повертає ця функція, можна зрозуміти, яка з двох
подій мала місце. Очікувати події за допомогою wait
-
функцій можна
відн
о
сно більшості об’єктів ядра, наприклад, щодо об’єктів
„
процес
”
або
„
нитка
”
–
щоб визначити, коли вони завершать свою роботу.
В
си
г-
нальний стан об’єкти переходять
у таких
ситуаціях:
▪
сповіщення
(
Change notification
)
–
при
змінах
у
файловій системі;
▪
введення з консолі (
Console input
)
–
при
готовності вв
едення
з
конс
о
лі;
▪
подія (
Event
)
–
при
виклику функцій
SetEvent
або
PulseEven
t
;
▪
завдання (
Job
)
–
при завершенні;
▪
м’ютекс (
Mutex
)
–
якщо
він
не належить жодній нитці;
▪
процес (
Process
)
–
при завершенні;
▪
семафор (
Semaphore
)
–
при
значенні більше 0;
▪
нитка (
Thread
)
–
при завершенні;
▪
таймер
(
Waitable
timer
)
–
при
настанні вка
заного часу
.
Функції
WaitForMultipleObjects
передається зразу масив об’єктів.
Можна очікувати спрацювання зразу всіх об’єктів або якогось одного з
них.
Параметри вказаних функцій:
DWORD WaitForSingleObject
(
HANDLE hHandle,
//
дескриптор об’єкт
а
DWORD dwMilliseconds
//
інтервал очікування
);
DWORD WaitForMultipleObjects
(
DWORD nCount, //
кількість дескрипторів
у
масиві
CONST HANDLE *lpHandles, //
масив
дескрипт
о
рів
//
об’єктів
BOOL bWaitAll, //
параметр чекання (всі або один)
DWORD dwMilliseconds
//
інтервал очікування
);
Приклад.
Програма створює дві однакових нитки і очікує їх заве
р-
ше
н
ня. Нитки просто виводять текстове повідомлення, яке передане їм
при їх ініціалізації.
Порядок вив
едення
повідомлення від першої та др
у-
гої
нитки зумовлюється порядком їх виконання та не залежить від п
о-
рядку створе
н
ня.
#include <windows.h>
unsigned ThreadFunc
(void * arg)
{
char ** str = (char**)arg;
MessageBox
(0,str[0],str[1],0);
ExitThread
(0);
return 0;
}
int main(int argc, char* argv[]
)
{
char * InitStr1[2] = {"First thread","11111"};
char * InitStr2[2] = {"Second thread","22222"};
unsigned long uThreadIDs[2];
HANDLE hThreads[2];
hThreads[0] = CreateThread
(NULL,0,
(LPTHREAD_START_ROUTINE)ThreadFunc,
InitStr1, 0,&uThreadIDs[0]);
hThr
eads[1] = CreateThread
(NULL,0,
(LPTHREAD_START_ROUTINE)ThreadFunc,
InitStr2, 0,&uThreadIDs[1]);
//
Очікування завершення роботи ниток
WaitForMultipleObjects
(2,
hThreads, TRUE, INFINITE);
//
Закриття дескрипторів
CloseHandle
(hThreads[0]);
CloseHandle
(h
Threads[1]);
return 0;
}
1.1.
5
.
Завдання
Завдання
(Job)
–
це об’єкт ядра
ОС
, що забезпечує керування о
д-
ним або декількома процесами як однією групою. Процес може входити
одночасно тільки до одн
ого
за
в
д
ання
,
і видалити процес із за
в
да
ння
н
е-
можливо. Всі про
цеси, яки будуть запущені з процесу, що вже входить
до за
в
да
ння
, також будуть входити до т
ого
ж за
в
да
ння
.
За допомогою
за
в
д
ань
можна встановлювати цілий ряд обмежень на виконання проц
е-
сів, що входять
до
за
в
да
ння
, при чому більшість обмежень не доступна
при
звичайному керуванні процесами. Саме тому для розширеного к
е-
рування яким
-
небудь пр
о
цесом доцільно створювати за
в
да
ння
, куди цей
процес необхідно підкл
ю
чити
.
Для роботи з за
в
да
ннями
використовуються
такі
функції.
AssignProcessToJobObject
–
д
одавання процес
у
з дескриптором
hProcess
в існуюч
е
за
в
да
ння
з дескриптором
hJob
:
BOOL AssignProcessToJobObject
(
HANDLE hJob, //
дескриптор за
в
да
ння
HANDLE hProcess //
дескриптор процесу
);
CreateJobObject
–
с
творення об’єкт
а
-
за
в
да
ння
з ім’ям
lpName
.
HANDLE Cre
ateJobObject
(
LPSECUR
ITY_ATTRIBUTES lpJobAttributes,
//
інформація
про з
а
хист
LPCTSTR lpName //
необов’язкове ім’я за
в
да
н
ня
);
IsProcessInJob
–
п
еревірка, чи входить процес
з дескриптором
ProcessHandle
у за
в
да
ння
з дескриптором
JobHandle
.
BOOL IsPr
ocessInJob (
HANDLE ProcessHandle, //
дескриптор процесу
HANDLE JobHandle, //
дескриптор за
в
да
ння
PBOOL Result //
покажчик на результат
);
Відкриття існуючого об’єкт
а
-
за
в
да
ння
з іменем
lpName
виконує
фун
к
ція
OpenJobObject
.
HANDLE OpenJobO
bject
(
DWORD dwDesiredAccess, //
права доступу
BOOL bInheritHandles, //
дозвіл наслідування
LPCTST
R lpName
//
ім’я за
в
да
ння
);
Функція
QueryInformationJobObject
дозволяє о
трима
ти
інформ
а-
ці
ю
про за
в
да
ння
з дескриптором
hJob
, а саме
:
обсяг в
икористаного
процесорного часу, лічильник кількості сторінкових відмов, пер
е
лік
ідентифікаторів процесів, обмеження захисту.
В полі
JobObjectInfoClass
задається тип інформації, а в полі
lpJobObjectInfo
–
покажчик на відп
о-
відну стру
к
туру.
BOOL QueryInforma
tionJobObject
(
HANDLE hJob,
//
дескриптор за
в
да
ння
JOBOBJECTINFOCLASS JobObjectInfoClass, //
клас
//
інфо
р
мації про за
в
да
ння
LPVOID lpJobObjectInfo, //
інформація про
//
обмеже
н
ня
д
ля вказаного класу
DWORD cbJobObjectInfoLength, //
розмір от
риманої
//
інф
о
рмації
LPDWORD lpReturnLength
//
розмір даних, що
//
зап
и
сані
в структурі, на яку посилається
//
lpJobObjectInfo
);
Встанов
ити
обмежен
ня
на процес
и
, що належать
за
в
да
нн
ю
з д
е-
скриптором
hJob
,
дозволяє функція
SetInformationJobOb
ject
, призн
а-
чення
ї
ї параметрів
таке саме, як і в функції
QueryInformationJobObject
.
BOOL SetInformationJobObject
(
HANDLE hJob, //
дескриптор за
в
да
ння
JOBOBJECTINFOCLASS JobObjectInfoClass, //
клас
//
інфо
р
мації про за
в
да
ння
LPVOID lpJobObject
Info //
інформація про обмеження
//
для вказаного класу
DWORD cbJobObjectInfoLength //
розмір отрим
а
ної
//
інф
о
рмації
);
За допомогою функцій
QueryInformationJobObject
та
SetInformationJobObject
можна отримувати або вносити
обмеження,
що перера
ховані нижче
(формат структур можна отримати в відпові
д-
них ро
з
ділах MSDN)
.
1)
Базові обмеження
(значення параметра
функцій
JobObjectInfoClass
= JobObjectBasicLimitInformation,
lpJobObjectInfo
вказує на структуру JOBOBJECT_BASIC_LIMIT_INFORMATION або
JobObj
ectInfoClass
= JobObjectExtendedLimitInformation,
lpJobObjectInfo
вк
а
зує
на
структуру
JOBOBJECT_EXTENDED_LIMIT_
INFORMATION)
.
▪
Максимальна кількість
активних процесів
–
обмеження на кіл
ь-
кість процесів, що одночасно виконуються.
▪
Загальн
е обмеження на про
цесорний час у
режимі користувача
–
о
б
меження процесорного часу на всі процеси, що входять до за
в
да
ння
.
Я
кщо час буде вичерпано
–
всі процеси будуть завершені примусово.
▪
Індивідуальне обмеження на процесорний час
у
режимі корист
у-
вача
–
обмеження процесор
ного часу для кожного процесу окремо. В
разі вик
о
ристання всього часу
–
процес буде примусово завершений.
▪
Клас планування за
в
да
ння
–
встановлюється довжина квант
а
часу
для ниток процесів, які входять до за
в
да
ння
.
▪
Прив’язування до процесорів
–
для кожно
го процесу встановл
ю-
ється маска прив’язування до процесор
а
(
для багатопроцесорних
комп’ютерів
)
.
▪
Клас пріоритету для всіх процесів
–
обмеження максимального
прі
о
ритету для кожного процесу. Якщо нитка спробує підвищити свій
пріор
и
тет
–
він
залишається
без
зміни, але помилки виконання операції
не б
у
де.
▪
Мінімальний та максимальний розміри робочого набору
–
для
кожного процесу встановлюються обмеження на робочий набір
, тобто
на кіл
ь
кість сторінок, що постійно знаходяться в оперативній пам'яті
.
Р
озмір зад
а
єть
ся в байта
х
.
▪
Обмеження віртуальної пам’яті
–
вказується максимальний ро
з-
мір віртуального адресного простору, який можна передати процесу або
вс
ьому
з
а
в
да
нню
.
2)
Базові обмеження інтерфейсу користувача
(значення параметр
а
ф
у
нкцій
JobObjectInfoClass
=
JobO
bjectBasicUIRestrictions
,
lpJobObjectInfo
вк
а
зує на структуру
JOBOBJECT_BASIC_
UI_RESTRICTIONS
)
.
▪
Заборона роботи з буфером обміну
–
обмеження читання та оч
и-
ще
н
ня буфер
а
обміну.
▪
Заборона завершення роботи системи
–
забороняється вихід з с
и-
ст
е
ми або заве
ршення роботи всієї системи через функцію
ExitWindowsEx
.
▪
Заборона зміни системних параметрів
–
кожному процесу забор
о-
няється змінювати параметри системи за допомогою функції
SystemParametersInfo
.
До
системних
параметрів відносяться: параме
т-
ри робочого ст
ол
а
, пристрою вв
едення
, системного меню, вікон пр
о-
грам, жи
в
лення
і
програми збереження екран
а
та
ін
.
▪
Заборона зміни параметрів екран
а
–
забороняється зміна параме
т-
рів за допомогою функції
ChangeDisplaySettings
.
▪
Заборона створення та перемикання робочих
столів
–
заборон
я-
ється використання функцій
CreateDesktop
та
SwitchDesktop
.
▪
Заборона користування USER
-
об’єктами, що не входять у за
в
да
н-
ня
–
процеси у за
в
да
нн
і не можуть звернутися до будь
-
яких USER
-
об’єктів, що створені зовнішніми до за
в
да
ння
процесами
. Наприклад,
неможливо отр
и
мати HWND дескриптор процесу, який не входить у
за
в
да
ння
.
3)
Базові обмеження захисту
(значення параметр
а
функцій
JobObjectInfoClass
=
JobObjectSecurityLimitInformation
,
lpJobObjectInfo
вк
а
зує на структуру
JOBOBJECT_SECURITY_LIMI
T_INFORMATION
)
.
Примітка
:
якщо в за
в
да
нн
і ввести такі обмеження, скасувати їх
буде неможл
и
во.
▪
Заборона доступу адміністратору.
▪
Заборона маркер
а
необмеженого доступу.
▪
Блокування доступу
–
блокується доступ по ідентифікаторам з
а-
хисту (Security ID).
Якщ
о задати в функції
QueryInformationJobObject
в параметрі
JobObjectInfoClass
значення JobObjectBasicAccountingInformation
,
JobObjectBasicAndIoAccountingInformation або
JobObjectBasicProcessIdList
,
можна отримати статистичну інформацію
про за
в
да
ння
, а саме
:
в першому випадку
–
про кількість процесів
у
з
а-
в
да
нн
і, процесорний час, кількість сторінкових відмов
;
у
другому вип
а-
дку
–
про кількість операцій читання, запису та про кількість переданих
байтів
;
у
третьому випадку
–
перелік ідентифікаторів процесів, що вх
о-
дять до за
в
да
ння
. В п
а
раметрі
lpJobObjectInfo
відповідно повинен бути
покажчик на структуру JOBOBJECT_BASIC_ACCOUNTING_
INFORMATION
,
або
JOBOBJECT_BASIC_AND_IO_ACCOUNTING_
INFORMATION
,
або JOBOBJECT_BASIC_PROCESS_ID_LIST.
Завершення всіх процесів у за
в
да
н
н
і з ідентифікатором
hJob
може
в
и
конуватися за допомогою функції
TerminateJobObject
:
BOOL TerminateJobObject
(
HANDLE hJob, //
дескриптор за
в
да
ння
UINT uExitCode //
код завершення
);
Приклад.
У
програмі, що
наведен
а нижч
е,
в змінну
lpszSystemInfo
з
аноситься
шлях до системного каталогу Windows
,
який
повертається
фун
к
цією
GetSystemDirectory
,
та додається до нього ім’я програми
calc.exe.
Далі створюється за
в
да
ння
MyJob
з дескриптором
hJob
, для
н
ього
встановлюється обмеження
(
з групи
базов
их
обмежен
ь
)
н
а кіл
ь-
кість активних проц
е
сів (4) та виконується спроба запустити та додати
10
процесів з програми ca
lc.exe. Далі програма очікує 15
секунд та зав
е-
ршує примусово всі
проц
е
си
в за
в
д
а
нн
і.
Як результат
–
буде створено
10
процесів, але одразу при додаванні їх
в за
в
да
ння
, тільки перші чот
и-
ри
будуть активними, інші будуть примусово завершені.
Примітка
: п
е-
рший рядок програми вказує, що пр
о
грама призначена для роботи в
ОС
Windows
2000 або вище,
оскільки
підтримка за
в
да
нь
у
сист
е
мах
Windows
95, 98 відсутня.
#define
_WIN32_WINNT 0x500
#include <windows.h>
#include <stdio.h>
HANDLE hJob;
LPTSTR lpszSystemInfo;
TCHAR tchBuff[MAX_PATH+1];
STARTUPINFO si;
PROCESS_INFORMATION pi;
int AddProcess2Job(void)
{
for (int i=0;i<10;i++)
{
ZeroMemory (&si, sizeof(si));
si.cb = s
izeof(si);
ZeroMemory (&pi, sizeof(pi));
if
(!CreateProcess (NULL,
tchBuff,
NULL,
NULL,
FALSE,
0, NULL, NULL, &si, &pi))
return 0;
AssignProcessToJobObject (hJob,pi.hProcess);
}
}
int main(int argc, char* argv[])
{
JOBOBJECT_BASIC_LIMIT_INFORMATIO
N jInfo;
lpszSystemInfo = tchBuff;
GetSystemDirectory
(lpszSystemInfo, MAX_PATH+1);
w
sprintf
(tchBuff,"%s
\
\
calc.exe",lpszSystemInfo);
hJob = CreateJobObject
(NULL, "MyJob");
jInfo.LimitFlags = JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
jInfo.ActiveProcessLimit = 4;
SetInformationJobObject
(hJob,
JobObjectBasicLimitInformation, &jInfo,
sizeof(jInfo));
AddProcess2Job
();
Sleep
(15000);
TerminateJobObject
(hJob,0);
return 0;
}
1.2.
Контрольні
завдання
Розробити консольну програму в середовищі програмування Visual
C
+
+
, яка реалізує простий менеджер програм: дозволяє запускати вказ
а-
ні програми та завершувати їх
(за вибором користувача)
згідно з вим
о-
гами, що задаються варіантами
,
наведеними
нижче
.
При завершенні р
о-
боти ро
з
робленого менеджер
а
всі запущені ним програми по
винні бути
примусово завершені.
Для реалізації обов’язково використовувати ни
т-
ки (або волокна) та за
в
да
ння
.
1
.
Запуск необмеженої кількості програм калькуляторів
(сalc.exe)
,
кожна з
яких
виконується не більше 10
секунд.
2
.
Запуск програм калькулятор
а
(calc
.exe)
, графічного редактора
Paint
(mspaint.exe)
та блокнота
(notepad.exe)
загальною кількістю не б
і-
льше 5
екземплярів.
3
.
Запуск програм калькулятора
(сalc.exe)
та графічного редактора
Paint
(mspaint.exe)
кількі
с
тю не більше трьох
екземплярів кожн
а
.
4
.
Зап
уск програм калькулятора
(сalc.exe)
, графічного редактора
Paint
(mspaint.exe)
та бло
к
нота
(notepad.exe)
не більш
ніж
по
одному
екземпляру та їх вибіркове завершення.
5
.
Запуск необмеженої кількості програм калькулятора
(сalc.exe)
та
вибіркове їх завершення
(передбачити також одночасне завершення всіх
копій).
6
.
Запуск
не більше 10 копій одночасно
редакторів WordPad
(write.exe)
з заб
о
роною використання
для них
буфер
а
обміну.
7
.
Запуск не більше
п’яти
редакторів WordPad
(write.exe)
, при зав
е-
ршенні роботи вида
ти всю доступну статистичну інформацію про роб
о-
ту редакторів.
8
.
Запуск не більше 10 програм калькуляторів
(сalc.exe)
, сумарний
час вик
о
нання яких не перевищує хвилин
и
.
9
.
Запуск будь
-
якої кількості програм калькулятора
(сalc.exe)
, гр
а-
фічного редактора Pai
nt
(mspaint.exe)
, блокнота
(notepad.exe)
та реда
к-
тор
а
WordPad
(write.exe)
,
та
вибіркове їх завершення або завершення
групами (групи ф
о
рмуються
за
типам
и
програм).
10
.
Запуск програм калькулятора
(сalc.exe)
, графічного редактора
Paint
(mspaint.exe)
, блокнот
а
(notepad.exe)
та редактора WordPad
(write.exe)
за
такою
схемою:
користувач
о
бирає, яку програму запуст
и-
ти
.
Я
кщо вказана програма завершується, автоматично запускається
наступна
із списку
,
і
так
для всіх програм
.
Користувач може
о
брати
будь
-
яку програму д
ля запуску, автоматично п
о
винні запускатися всі
інші програми із списку.
11
.
Запуск та завершення вказаних користувачем програм (ім
ена
зада
ю
ться з клавіатури, каталог для програм за замовчанням
–
систе
м-
ний).
За
команд
ою
з клавіатури також виводити перелік
назв файлів
програм, які були у
с
пішно запущені на виконання
,
та
з
віт
про невдалі
спроби запуску.