Відмінності між версіями «Тема 13. Моделювання станів процесів в Windows»

Матеріал з Вікі ЦДУ
Перейти до: навігація, пошук
 
(не показано 7 проміжних версій цього учасника)
Рядок 1: Рядок 1:
Ця стаття допоможе студентам при виконанні даної лабораторної роботи. Стаття написана з власного досвіду. Сьогодні ми будемо моделювати стани процесів в Windows з допомогою мови програмування С++ - всього їх розглянемо 5. Нам здадобляться [http://sourceforge.net/projects/dev-cpp/files/Binaries/Dev-C%2B%2B%204.9.9.2/devcpp-4.9.9.2_setup.exe/download?use_mirror=switch Dev-C++] для компіляції програм і [http://processhacker.sourceforge.net/ ProcessHacker] для їх моніторингу. Рядки вихідного коду програм мають нумерацію, що дозволить давати коментарі щодо загальних принципів роботи програм. Ці коментарі знаходятся у тому ж розділі статті, що і відповідний лістинг. На початку коментаря в дужках вказано номер рядка, до якого цей коментар стосується. Отже, до справи!
+
Ця стаття допоможе студентам при виконанні даної лабораторної роботи. Стаття написана з власного досвіду. Сьогодні ми будемо моделювати стани процесів в Windows з допомогою мови програмування С++ - всього їх розглянемо 5. Нам знадобляться [http://sourceforge.net/projects/dev-cpp/files/Binaries/Dev-C%2B%2B%204.9.9.2/devcpp-4.9.9.2_setup.exe/download?use_mirror=switch Dev-C++] для компіляції програм і [http://processhacker.sourceforge.net/ ProcessHacker] для їх моніторингу. Рядки вихідного коду програм мають нумерацію, що дозволить давати коментарі щодо загальних принципів роботи програм. Ці коментарі знаходятся у тому ж розділі статті, що і відповідний лістинг. На початку коментаря в дужках вказано номер рядка, до якого цей коментар стосується. У ProcessHacker різні типи потоків підсвічуються різними кольорами - якому кольору відповідає який тип, можна з"ясувати в налаштуваннях програми. Отже, до справи!
  
 
=new=
 
=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=
 
=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 <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=
 
=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 <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).

Поточна версія на 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).