Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

OS_metod

.pdf
Скачиваний:
10
Добавлен:
07.02.2016
Размер:
480.05 Кб
Скачать

31

2.4.4Текст скрипту L2_case_n, модифікованого згідно пп. 2.2.7.4* лабораторного завдання.

2.4.5Текст скрипту L2_info, розроблений згідно п. 2.2.8 лабораторного завдання.

2.4.6Відповіді на контрольні запитання.

32

3 ЛАБОРАТОРНА РОБОТА №3. УПРАВЛІННЯ ПРОЦЕСАМИ В UNIX

Мета роботи – ознайомитись з системними викликами для створення та управління процесами в OC UNIX.

3.1 Лабораторне завдання

3.1.1 Використання системного виклику fork(2). 3.1.1.1 Ознайомтесь з текстом програми L3_fork.c:

// Програма L3_fork.c: системний виклик fork #include <stdio.h>

#include <stdlib.h> #include <unistd.h> int main()

{

int A = 0, B=10; long pid;

printf("\nPID: %4ld A: %2d B: %2d\n", getpid(),A,B); pid = fork();

printf("\nPID: %4ld A: %2d B: %2d\n", getpid(),A,B); if (pid < 0)

{

perror("fork error"); exit(1);

}

if (pid == 0)

{

A = A + 10; B = B + 10;

}

else

{

A = A + 25; B = B + 25;

}

printf("\nPID: %4ld A: %2d B: %2d\n",getpid(),A,B); exit(0);

}

3.1.1.2 Відкомпілюйте та виконайте дану програму. Запишіть до звіту результати виводу програми. Поясніть значення змінних A та B.

3.1.1.3 Модифікуйте програму так, щоб тільки батьківський процес викликав функцію sleep, (наприклад, sleep(2);). Чи змінює

33

виклик функції sleep вивід, здійснюваний двома процесами? Чи змінюються остаточні значення змінних в двох процесах? Поясніть.

3.1.2 Використання системних викликів wait(2) та exit(2). 3.1.2.1 Ознайомтесь з текстом програми L3_wait.c. Зверніть увагу

на визначення функції display_status та використання макросів "W*", які перевіряють статус виконання виклику wait.

//Програма L3_wait.c: системні виклики exit, wait

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> void display_status(int); int main()

{pid_t pid; int status;

/*** Створити дочірній процес #1 ***/

pid = fork(); if (pid < 0)

{perror("fork error"); exit(1); } if (pid == 0)

{/* Дочірній процес - нормальне завершення */ exit(1);

}

else

{ /* Батьківський процес - чекання дочірнього */ if (wait(&status) != pid)

{ perror("wait error"); } display_status(status);

}

/*** Створити дочірній процес #2 ***/

pid = fork(); if (pid < 0)

{perror("fork error:"); exit(1); } if (pid == 0)

{/* Дочірній процес - генерація SIGABRT */

abort();

exit(2);

}

34

else

{ /* Батьківський процес - чекання дочірнього */ if (wait(&status) != pid)

{

perror("wait error"); exit(1);

}

display_status(status);

}

/*** Створити дочірній процес #3 ***/

pid = fork(); if (pid < 0)

{

perror("fork error"); exit(1);

}

if (pid == 0)

{// Дочірній процес: ділення на 0 - генерація SIGFPE int num = 20;

num = num / 0; exit(3);

}

else

{

if (wait(&status) != pid) { perror("wait error"); } display_status(status);

}

exit(0);

}

void display_status(int stat)

{

if (WIFEXITED(stat))

printf("\nNormal termination, exit status %d\n", WEXITSTATUS(stat));

else if (WIFSIGNALED(stat))

printf("\nAbnormal termination, signal number %d\n", WTERMSIG(stat));

else printf("\nAnother problem detected\n");

}

3.1.2.2 Виконайте програму, результати виводу подайте у звіті, дайте відповідь на наступні питання:

35

який рядок коду повинний бути змінений, щоб перший рядок виводу мав статус завершення, що відрізняється від 1?

яке ціле число відповідає сигналу арифметичного виключення?

поясніть, чому не жодний з дочірніх процесів не викликає функцію wait?

3.1.2.3 Модифікуйте програму так, щоб створювався четвертий дочірній процес, який би завершувався за помилкою сегментації пам’яті. Чи змінює додавання четвертого процесу вивід, що здійснюється першими трьома процесами? Поясніть.

3.1.3 Використання системного виклику exec(2).

3.1.3.1Ознайомтесь з програмами L3_exec.c та L3_display.c.

// Програма L3_exec.c: використання execle и execlp #include <stdio.h>

#include <stdlib.h> #include <unistd.h> #include <sys/wait.h>

char* env_init[]={"USER=unknown", "PATH=/tmp", NULL}; int main()

{

pid_t pid;

int flag, status;

/*** Створення дочірнього процеса #1 ***/

pid = fork();

if (pid < 0) perror("fork error"); if (pid == 0)

{ // Дочірній процес - замінити іншою програмою flag = execle("/home/logname/os/lab3/l3_display", "l3_display", "arg1", "arg2", NULL, env_init);

if (flag < 0) perror("execle error");

}

else

{// Батьківський процес: чекає завершення дочірнього if (wait(&status) != pid)

perror("wait error");

}

/*** Створення дочірнього процеса #2 ***/

pid = fork();

if (pid < 0) perror("fork error");

36

else if (pid == 0)

{ // Дочірній процес - замінити іншою програмою flag = execlp("./l3_display", "l3_display",

"arg1", "arg2", "arg3", NULL);

if (flag < 0) perror("execlp error");

}

else

{//Батьківський процес: чекає завершення дочірнього if (wait(&status)!=pid) perror("wait error");

}

exit(0);

}

//Програма L3_display: вивід всіх аргументів

//командного рядка та змінних середовища

#include <stdio.h> #include <stdlib.h>

int main(int argc, char *argv[], char* environ[]) { int i; char **ptr;

/* Вивести всі аргументи командного рядка */ printf("\n");

for (i = 0; i < argc; i++) printf("argv[%d]: %s\n", i, argv[i]);

printf("\n");

/* Вивести всі аргументи командного рядка */ for (ptr = environ; *ptr != 0; ptr++)

printf("%s\n", *ptr); printf("\n");

exit(0);

}

3.1.3.2 Відкомпілюйте обидві програми, замініть у файлі L3_exec.c в першому параметрі функції execle елемент logname на ім’я Вашого домашнього каталогу. Виконайте програму L3_exec. Для зручності результат виводу програми збережіть у файлі. Дайте відповідь на наведені питання:

де розташовується та яку назву має програма, що виконується за допомогою виклику exec?

скільки разів дана програма виконується?

поясніть різницю виводу при використанні двох різних функцій exec;

37

перемістіть файл L3_display до каталогу /home/logname та виконайте програму знову. Поясніть помилки.

3.1.3.3 Модифікуйте програму L3_exec.c в програму L3_exec_n.c, яка використовує системний виклик execvp замість execlp. Зверніть увагу, що execvp використовує масив рядків, де кожний рядок є аргументом командного рядка (як у функції main). Можна оголосити цей тип даних за допомогою char *buf[10], який містить 10 покажчиків на рядки. Даний фрагмент програми подайте у звіті.

3.2 Контрольні запитання

3.2.1Що означає створення нового процесу? Як створити новий процес в UNIX? Який системний виклик використовується для даної мети?

3.2.2Як запустити задану програму в щойно створеному процесі?

3.2.3Опишіть використання системного виклику wait(2).

3.2.4Для чого використовується системний виклик exit(2)?

3.2.5Як проаналізувати завершення роботи процесу?

3.3 Зміст звіту

3.3.1Тема та мета роботи.

3.3.2Результати виводу програми, отримані при виконанні пп. 3.1.1.2 лабораторного завдання.

3.3.3Відповіді на питання пп. 3.1.2.2 лабораторного завдання.

3.3.4Фрагмент модифікованої програми згідно з пп. 3.1.2.3 лабораторного завдання.

3.3.5Відповіді на питання пп. 3.1.3.2 лабораторного завдання.

3.3.6Фрагмент модифікованого коду згідно з пп. 3.1.3.3 лабораторного завдання.

3.3.7Відповіді на контрольні питання.

38

4 ЛАБОРАТОРНА РОБОТА №4. УПРАВЛІННЯ ПАМ’ЯТЮ: СТОРІНКОВА ОРГАНІЗАЦІЯ ПАМ’ЯТІ, АЛГОРИТМИ ВІРТУАЛЬНОЇ ПАМ’ЯТІ

Мета роботи – вивчити сторінкову організацію пам’яті, перетворення логічної адреси в фізичну; ознайомитись з алгоритмами заміщення сторінок при управлінні віртуальною пам’ятю.

4.1 Загальні відомості Алгоритми заміщення сторінок процесів

Коли всі кадри оперативної пам’яті зайняті і потрібно розмістити нову сторінку, стратегія заміщення визначає, яка з сторінок, що знаходяться в поточний час в оперативній пам’яті має бути вивантажена, щоб звільнити кадр для завантажуваної сторінки. Всі стратегії направлені на те, щоб вивантажити сторінку, звернень до якої в близькому майбутньому не відбудеться. Відповідно до принципу локалізації часто спостерігається сильна кореляція між множиною сторінок, до яких були звернення в останній час, та множиною сторінок, до яких будуть звернення в найближчий час. Таким чином, більшість стратегій намагаються визначити майбутню поведінку програми на основі її попередньої поведінки. Слід враховувати, що чим більш досконалий та інтелектуальний алгоритм використовує стратегія, тим вище будуть накладні витрати для її реалізації.

Існує ряд основних алгоритмів, що використовуються для вибору сторінки, що заміщується:

оптимальний алгоритм;

алгоритм "довше всіх невикористовувався" (least recently used – LRU);

алгоритм "перший увійшов – першим вийшов" (first in first out – FIFO);

годинниковий алгоритм.

Нижче наведені описи та характеристики згаданих алгоритмів, їх роботу пояснює рис. 4.1. Передбачається, що процес складається з 5 сторінок, а для його виконання доступні 3 кадри пам’яті.

4.1.1 Оптимальний алгоритм

Обирає для заміщення сторінку, звернення до якої буде через найбільший проміжок часу у порівнянні з іншими. Алгоритм

39

призводить до мінімальної кількості переривань через відсутність сторінки. Реалізувати такий алгоритм неможливо, оскільки потрібно знати всі наступні події системи. Проте даний алгоритм є стандартом, з яким порівнюються реальні алгоритми.

Звернення до

2

3

2

1

5

2

4

5

3

2

5

2

сторінок

 

 

 

 

 

 

 

 

 

 

 

 

Оптимальний

2

 

алгоритм

 

Алгоритм

2

довше всих

 

невикористо-

 

вуваного

 

Алгоритм

2

"першим війшов -

 

останнім вийшов"

 

2*

Годинниковий

алгоритм

2

3

2

3

2

3

2*

3*

2

3

2

3

2

3

2*

3*

2

2

2

3

3

3

1

5

5

 

F

 

2

2

2

3

5

5

1

1

1

 

F

 

2

5

5

3

3

2

1

1

1

 

F

F

2*

5*

5*

3*

3

2*

1*

1

1

 

F

F

4

3

5

F

2

5

4

F

5

2

4

F

5*

2*

4*

F

4

3

5

2

5

4

5

2

4

5*

2*

4*

4

3

5

3

5

4

F

3

2

4

F

3*

2

4

F

2

3

5

F

3

5

2

F

3

2

4

3*

2*

4

2

3

5

3

5

2

3

5

4

F

3*

2

5*

F

2

3

5

3

5

2

3

5

2

F

3*

2*

5*

Рисунок 4.1 – Поведінка чотирьох алгоритмів заміщення сторінок

4.1.2Алгоритм "довше всіх невикористовувався" (least recently used – LRU)

Заміщує в пам’яті сторінку, звернень до якої не було довше всіх. Згідно з принципом локалізації, очікується, що ця сторінка не буде використовуватись в ближньому майбутньому. Кожна сторінка повинна бути відзначена під час останнього звернення до неї. Цей алгоритм складний в реалізації, оскільки потребує великих накладних витрат, проте близький до оптимального.

4.1.3Алгоритм "першим увійшов – першим вийшов" (first in first out – FIFO)

Розглядає кадри сторінок процесу як циклічний буфер, сторінки вилучаються з нього циклічно. Для реалізації алгоритма потрібний

40

лише покажчик, який циклічно проходить по кадрам сторінок процесу. Це одна з найпростійших стратегій розміщення в реалізації. Заміщується сторінка, що знаходиться в оперативній пам’яті довше інших, проте, заміщені сторінки можуть знадобитися невдовзі знову. На рис. 4.1 даний алгоритм призводить до шести переривань через відсутність сторінки (відзначені буквою F). Алгоритм "довше всіх невикористовувався" роспізнає, що частіше інших використовуються сторінки 2 та 5, а алгоритм FIFO на це не здатний.

4.1.4 Годинниковий алгоритм

Використовує для кожного кадру додатковий біт – біт використання. Коли сторінка вперше завантажується до кадру, біт використання встановлюється в 1. При наступних зверненнях до сторінки, цей біт також встановлюється в 1. При роботі алгоритма заміщення множина кадрів, які є кандидатами на заміщення, розглядаються як циклічний буфер, з яким пов’язаний покажчик. При заміщенні сторінки покажчик переміщується до наступного кадру в буфері. На рис. 4.1 наявність зірочки свідчить, що біт використання сторінки дорівнює 1, а стрілка вказує поточне положення покажчика.

Коли надходить час заміщення сторінки, ОС сканує буфер для пошуку кадра, біт використання якого дорівнює 0; якщо в процесі пошуку зустрічається кадр з бітом використання, що дорівнює 1, він скидається в 0. Якщо всі кадри мають біт використання, який дорівнює 1, покажчик здійснює повний круг і повертається до початкового положення, замінюючи сторінку в цьому кадрі.

На рис. 4.2 більш детально проілюстрована робота годинникового алгоритма. Для заміщення доступні n-1 кадри оперативної пам’яті, які подаються у вигляді циклічного буфера. Безпосередньо перед тим, як замістити сторінку в буфері сторінкою 727, що завантажується з вторинної пам’яті, покажчик буфера вказує на кадр 2, який містить сторінку 45. Розглянемо виконання годинникового алгоритма в даному випадку. Оскільки біт використання сторінки 45 в кадрі 2 дорівнює 1, ця сторінка не заміщується; замість цього її біт використання скидається, а покажчик переміщується до наступного кадру. Не заміщується також сторінка 191 з кадру 3; у відповідності до алгоритма скидається її біт використання. В наступному кадрі (номер 4) біт використання сторінки дорівнює 0. Таким чином сторінка 556 заміщується

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]