Відмінності між версіями «Тема 13. Моделювання станів процесів в Windows»
| (не показані 4 проміжні версії цього учасника) | |||
| Рядок 2: | Рядок 2: | ||
=new= | =new= | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | DWORD ThreadProc (LPVOID lpdwThreadParam ); | + | #include <windows.h> |
| + | #include <stdio.h> | ||
| + | #include <stdlib.h> | ||
| + | DWORD ThreadProc (LPVOID lpdwThreadParam ); | ||
| + | //оголошення глобальної змінної , видимої всіма потоками | ||
| + | int nGlobalCount = 0; | ||
| + | //головна функція яка стартує всі інші потоки | ||
| + | int __cdecl main( int argc, char **argv) | ||
| + | { | ||
| + | int i, nThreads = 5;//кількість потоків що будуть створені | ||
| + | DWORD dwThreadId; | ||
| + | //Визначаємо кількість потоків, які будемо створювати | ||
| + | if (argc > 1) { | ||
| + | nThreads = atoi( argv[1]); | ||
| + | } | ||
| + | //Присвоюємо загальну кількість змінній кількості потоків | ||
| + | nGlobalCount = nThreads; | ||
| + | //Стартуємо нові потоки в циклі | ||
| + | for (i=1; i<= nThreads; i++) { | ||
| + | //printf("i - %d\n",i); | ||
| + | if (CreateThread(NULL, //1 Встановлюємо параметр безпеки дефолтним значенням | ||
| + | 0, //Розміп стеку потоку також залишаємо за замовчуванням | ||
| + | (LPTHREAD_START_ROUTINE)&ThreadProc, | ||
| + | //Далі йдуть команди ініціалізації потоку | ||
| + | (LPVOID) &i, //Запам"ятовуємо параметр потоку | ||
| + | 0, //і одразу ж запускаємо потік | ||
| + | &dwThreadId // Id потоку | ||
| + | ) == NULL) | ||
| + | {//в разі помилки створення потоку виводимо повідомлення користувачеві | ||
| + | printf("Error Creating Thread#: %d\n",i); | ||
| + | return(1);//і завершуємо програму | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | printf("Global Thread Count: %d %d %d\n", nGlobalCount, nThreads, i);//підсумкові інформація про створені потоки | ||
| + | Sleep(1000); | ||
| + | } | ||
| + | } | ||
| + | return 0; | ||
| + | } | ||
| + | //власна функція для роботи з потоком | ||
| + | DWORD ThreadProc (LPVOID lpdwThreadParam ) | ||
| + | { | ||
| + | //виводимо номер потоку | ||
| + | printf ("Thread #: %d\n", *((int*)lpdwThreadParam)); | ||
| + | //зменшення лічильника | ||
| + | nGlobalCount--; | ||
| + | //завершення роботи потоку | ||
| + | return 0; | ||
| + | } | ||
| − | + | Програма моделює створення нового потоку. Для створення нового потоку викликаємо системну функцію CreateThread (1). | |
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
=ready= | =ready= | ||
| − | + | #include <iostream> | |
| − | // | + | #include <windows.h> |
| − | + | int main () | |
| + | { | ||
| + | std::cout << "Message 1\n" ; | ||
| + | Sleep(2000); //1: число в мілісекундах . 1 секунда = 1000 мілісекунд | ||
| + | std::cout << "Message 2 a two seconds after Message 1" ; | ||
| + | return 0; | ||
| + | } | ||
| − | + | Ця програма створює потік , що примушує програму стати unrunnable на час інтервалу на підставі виклику функції Sleep(1). Системний годинник "цокає" з постійною швидкістю. Після того як інтервал очікування пройшов , потік готовий до роботи. Якщо вказати 0 мілісекунд , потік поступиться рештою свого часового строку, але як і раніше буде готовий. Зверніть увагу , що виконання готового потоку не гарантується відразу. Отже , потік не може не працювати , поки через деякий час після інтервалу закінчиться очікування . | |
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
=running= | =running= | ||
#include <time.h> | #include <time.h> | ||
| − | #include <conio.h> | + | #include <conio.h> |
| − | #include <iostream> | + | #include <iostream> |
| − | #include <string> | + | #include <string> |
| − | #include <windows.h> | + | #include <windows.h> |
| − | #define timer 5.0 | + | #define timer 5.0 |
| − | using namespace std; | + | using namespace std; |
| − | int main() | + | int main() |
| − | { | + | { |
| − | double dif=0; | + | double dif=0; |
| − | while(1) | + | while(1)//1 |
| − | { | + | { |
| − | dif+=1; | + | dif+=1;//2 |
| − | } | + | } |
| − | getch(); | + | getch(); |
| − | return 0; | + | return 0; |
| − | } | + | } |
| + | |||
| + | Потік у даному стані є потоком виконання. Виконання потоку легко забезпечити за допомогою безперервного цикла (1) і певних дій (2) в його тілі. | ||
=terminated= | =terminated= | ||
| − | // | + | #include <time.h> |
| − | // | + | #include <conio.h> |
| + | #include <iostream> | ||
| + | #include <string> | ||
| + | #include <windows.h> | ||
| + | #define timer 5.0//1 | ||
| + | using namespace std; | ||
| + | int main() | ||
| + | { | ||
| + | double dif=0; | ||
| + | time_t start,end; | ||
| + | time(&start);//2 | ||
| + | string s; | ||
| + | while(dif<timer) //Інціалізація зворотнього відліку | ||
| + | { | ||
| + | printf("Type a word after %.0lf seconds..\nYour Time starts in..\n",timer); | ||
| + | time (&end); | ||
| + | dif = difftime(end,start);//обчислення часу що залишився до кінця зворотного відліку | ||
| + | printf( "%.0lf seconds\n", timer-dif);//скільки секунд залишилося | ||
| + | Sleep(1000);//системна затримка | ||
| + | system("CLS");//очистка екрану | ||
| + | } | ||
| + | HANDLE h_to_console=GetStdHandle( STD_INPUT_HANDLE );//визначання контектсу вводу (простіше кажучи консолі) | ||
| + | FlushConsoleInputBuffer(h_to_console);//перенаправлення потоку виводу на цю консоль | ||
| + | cout<<"Enter the String:\n";//3 | ||
| + | cin>>s; | ||
| + | cout<<"You have Entered: "<<s; | ||
| + | getch();//затримка еурану - щоб можна було отримати результат | ||
| + | return 0; | ||
| + | } | ||
| − | + | Ідея полягає в тому щоб примусити Консоль чекати 'T' секунд для входу (1). Ця програма має таймер зворотного відліку (2). Після зворотного відліку починається введення сесія (3). | |
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
| − | + | ||
=waiting= | =waiting= | ||
| − | #include <time.h> | + | #include <time.h> |
| − | #include <conio.h> | + | #include <conio.h> |
| − | #include <iostream> | + | #include <iostream> |
| − | #include <string> | + | #include <string> |
| − | #include <windows.h> | + | #include <windows.h> |
| − | #define timer 5.0 | + | #define timer 5.0 |
| − | using namespace std; | + | using namespace std; |
| − | int main() | + | int main() |
| − | { | + | { |
| − | + | ||
string s; | string s; | ||
| − | cout<<"Enter the String:\n"; | + | cout<<"Enter the String:\n"; |
| − | cin>>s; | + | cin>>s;//1 |
| − | cout<<"You have Entered: "<<s; | + | cout<<"You have Entered: "<<s; |
| − | getch(); | + | getch(); |
| − | return 0; | + | return 0; |
| − | } | + | } |
| + | |||
| + | Потік стає потоком очікування , коли очікує на певну подію, дані, тощо. У нашому випадку програма чекає на введення користувачем текстового рядка (1). | ||
Поточна версія на 21:36, 13 грудня 2013
Ця стаття допоможе студентам при виконанні даної лабораторної роботи. Стаття написана з власного досвіду. Сьогодні ми будемо моделювати стани процесів в Windows з допомогою мови програмування С++ - всього їх розглянемо 5. Нам знадобляться Dev-C++ для компіляції програм і ProcessHacker для їх моніторингу. Рядки вихідного коду програм мають нумерацію, що дозволить давати коментарі щодо загальних принципів роботи програм. Ці коментарі знаходятся у тому ж розділі статті, що і відповідний лістинг. На початку коментаря в дужках вказано номер рядка, до якого цей коментар стосується. У ProcessHacker різні типи потоків підсвічуються різними кольорами - якому кольору відповідає який тип, можна з"ясувати в налаштуваннях програми. Отже, до справи!
new
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
DWORD ThreadProc (LPVOID lpdwThreadParam );
//оголошення глобальної змінної , видимої всіма потоками
int nGlobalCount = 0;
//головна функція яка стартує всі інші потоки
int __cdecl main( int argc, char **argv)
{
int i, nThreads = 5;//кількість потоків що будуть створені
DWORD dwThreadId;
//Визначаємо кількість потоків, які будемо створювати
if (argc > 1) {
nThreads = atoi( argv[1]);
}
//Присвоюємо загальну кількість змінній кількості потоків
nGlobalCount = nThreads;
//Стартуємо нові потоки в циклі
for (i=1; i<= nThreads; i++) {
//printf("i - %d\n",i);
if (CreateThread(NULL, //1 Встановлюємо параметр безпеки дефолтним значенням
0, //Розміп стеку потоку також залишаємо за замовчуванням
(LPTHREAD_START_ROUTINE)&ThreadProc,
//Далі йдуть команди ініціалізації потоку
(LPVOID) &i, //Запам"ятовуємо параметр потоку
0, //і одразу ж запускаємо потік
&dwThreadId // Id потоку
) == NULL)
{//в разі помилки створення потоку виводимо повідомлення користувачеві
printf("Error Creating Thread#: %d\n",i);
return(1);//і завершуємо програму
}
else
{
printf("Global Thread Count: %d %d %d\n", nGlobalCount, nThreads, i);//підсумкові інформація про створені потоки
Sleep(1000);
}
}
return 0;
}
//власна функція для роботи з потоком
DWORD ThreadProc (LPVOID lpdwThreadParam )
{
//виводимо номер потоку
printf ("Thread #: %d\n", *((int*)lpdwThreadParam));
//зменшення лічильника
nGlobalCount--;
//завершення роботи потоку
return 0;
}
Програма моделює створення нового потоку. Для створення нового потоку викликаємо системну функцію CreateThread (1).
ready
#include <iostream>
#include <windows.h>
int main ()
{
std::cout << "Message 1\n" ;
Sleep(2000); //1: число в мілісекундах . 1 секунда = 1000 мілісекунд
std::cout << "Message 2 a two seconds after Message 1" ;
return 0;
}
Ця програма створює потік , що примушує програму стати unrunnable на час інтервалу на підставі виклику функції Sleep(1). Системний годинник "цокає" з постійною швидкістю. Після того як інтервал очікування пройшов , потік готовий до роботи. Якщо вказати 0 мілісекунд , потік поступиться рештою свого часового строку, але як і раніше буде готовий. Зверніть увагу , що виконання готового потоку не гарантується відразу. Отже , потік не може не працювати , поки через деякий час після інтервалу закінчиться очікування .
running
#include <time.h>
#include <conio.h>
#include <iostream>
#include <string>
#include <windows.h>
#define timer 5.0
using namespace std;
int main()
{
double dif=0;
while(1)//1
{
dif+=1;//2
}
getch();
return 0;
}
Потік у даному стані є потоком виконання. Виконання потоку легко забезпечити за допомогою безперервного цикла (1) і певних дій (2) в його тілі.
terminated
#include <time.h>
#include <conio.h>
#include <iostream>
#include <string>
#include <windows.h>
#define timer 5.0//1
using namespace std;
int main()
{
double dif=0;
time_t start,end;
time(&start);//2
string s;
while(dif<timer) //Інціалізація зворотнього відліку
{
printf("Type a word after %.0lf seconds..\nYour Time starts in..\n",timer);
time (&end);
dif = difftime(end,start);//обчислення часу що залишився до кінця зворотного відліку
printf( "%.0lf seconds\n", timer-dif);//скільки секунд залишилося
Sleep(1000);//системна затримка
system("CLS");//очистка екрану
}
HANDLE h_to_console=GetStdHandle( STD_INPUT_HANDLE );//визначання контектсу вводу (простіше кажучи консолі)
FlushConsoleInputBuffer(h_to_console);//перенаправлення потоку виводу на цю консоль
cout<<"Enter the String:\n";//3
cin>>s;
cout<<"You have Entered: "<<s;
getch();//затримка еурану - щоб можна було отримати результат
return 0;
}
Ідея полягає в тому щоб примусити Консоль чекати 'T' секунд для входу (1). Ця програма має таймер зворотного відліку (2). Після зворотного відліку починається введення сесія (3).
waiting
#include <time.h>
#include <conio.h>
#include <iostream>
#include <string>
#include <windows.h>
#define timer 5.0
using namespace std;
int main()
{
string s;
cout<<"Enter the String:\n";
cin>>s;//1
cout<<"You have Entered: "<<s;
getch();
return 0;
}
Потік стає потоком очікування , коли очікує на певну подію, дані, тощо. У нашому випадку програма чекає на введення користувачем текстового рядка (1).