Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Metodychka-lab_OS.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
1.35 Mб
Скачать

Додаток 1

Програма друку назви системної валюти

(вказується користувачем при інсталяції ОС).

.386

.model flat, stdcall

include c:\masm32\include\windows.inc

include c:\masm32\include\kernel32.inc

include c:\masm32\include\advapi32.inc

include c:\masm32\include\user32.inc

include c:\masm32\include\masm32.inc

includelib c:\masm32\lib\kernel32.lib

includelib c:\masm32\lib\user32.lib

includelib c:\masm32\lib\masm32.lib

includelib c:\masm32\lib\advapi32.lib

.data

Subkey db "Control Panel\International\",0

hkey dd ?

val_n db "sCurrency",0

val db 255 dup (0)

val_l dd 255

.code

start:

invoke RegOpenKeyEx,HKEY_CURRENT_USER, addr Subkey, 0, KEY_EXECUTE, addr hkey

invoke RegQueryValueEx, hkey, addr val_n, 0, NULL, addr val, addr val_l

invoke MessageBox,0 , addr val, addr val, 0

invoke ExitProcess,0

end start

Лабораторна робота №6

Тема: Ствоення обчислювальних процесів та потоків в ОС Linux.

Мета: Навчитися програмним шляхом породжувати обчислювальні процеси та потоки в UNIX подібних операційних системах.

1. Основні теоретичні відомості

    1. Породження процесів

Звичайно, новий процес в Unix-подібних операційних системах створюється за допомогою системного виклику fork():

#include <sys/types.h>

#include <unistd.h>

pid_t fork(void);

Функція fork() створює новий процес, який відрізняється від батьківського лише своїм номером в системі. Тобто відбувається копіювання всього адресного простору та таблиці відкритих файлових дескрипторів батьківського процесу. При успішному виконанні функція fork() повертає номер нового процесу в системі, інакше повертається -1 і глобальна змінна errno встановлюється у відповідне значення. Детальніше про можливі значення errno можна дізнатися з on-line допомоги по функції fork() командою man.

Далі необхідно асоціювати новостворений процес з конкретною задачею, що робиться за допомогою системного виклику execve():

#include <unistd.h>

int execve(const char *filename, char *const argv [], char *const envp []);

Функція execve() виконує програму filename, з аргументами командної стрічки argv та масивом змінних оточення envp. При успішному виклику функція execve() не повертається, інакше повертається -1 і встановлюється глобальна змінна errno. Детальніше про можливі коди помилки - в on-line документації по execve().

Таким чином наступний фрагмент коду реалізує послідовність дій по створенню нового процесу:

...

/* батьківський процес */

...

pid_t child;

if ((child = fork()) > 0)

{

...

/* код породженого процесу */

if ((execve("нова_програма", 0, 0)) < 0)

{

perror("execve ");

exit(1);

}

} else if (child < 0)

{

perror("fork ");

exit(1);

}

/*

батьківський процес продовжує своє виконання тут

*/

...

Ось приклад програми, що запускає новий процес і передає йому його номер в системі, повернений функцією fork(). Породжений процес в свою чергу в нескінченному циклі виводить свій номер на пристрій stdout. Батьківський процес після створення нового процесу також у нескінченному циклі виводить на stdout стрічку "parent\n". Таким чином можна бачити, коли виконується породжений процес, а коли батьківський.

Код батьківського процесу:

/* parent.c */

#include <stdio.h>

#include <sys/types.h>

#include <unistd.h>

#define DELAY 100000000

int main(int argc, char **argv)

{

int i;

pid_t child_1;

char **argv_c;

argv_c = (char **)calloc(1, sizeof(char **));

if (! argv_c)

{

perror("calloc ");

exit(1);

}

argv_c[0] = (char *)calloc(1, 256);

if (! argv_c[0])

{

perror("calloc ");

exit(1);

}

if ((child_1 = fork()) > 0)

{

sprintf(argv_c[0], "%d", child_1);

if (execve("child", argv_c, 0) < 0)

{

perror("execve :");

exit(1);

}

} else

if (child_1 < 0)

{

perror("fork :");

exit(1);

}

free(argv_c[0]);

free(argv_c);

for (;;)

{

printf("parent\n");

for (i = 0; i < DELAY; i++)

;

}

return 0;

}

Код породженого процесу:

/* child.c */

#include <stdio.h>

#include <stdlib.h>

#define DELAY 100000000

int main(int argc, char *argv[])

{

int i;

for (;;)

{

fprintf(stdout, "%s%s%s","child ", argv[0], "\n");

for (i = 0; i < DELAY; i++)

;

}

return 0;

}

Компіляція parent.c та child.c відбувається наступним чином:

$ gcc -o parent parent.c

$ gcc -o child child.c

$ ./parent

parent

child 1866

child 1866

parent

child 1866

parent

parent

child 1866

child 1866

parent

Потрібно зазначити, що викликати функцію execve() одразу після fork() не завжди обов'язково. Це робиться лише тоді, коли ми хочемо з нашої програми запустити на виконання нову задачу. Але якщо потрібно провести деякі обчислення або операції, і ми не хочемо, щоб вони блокували головний потік виконання програми, то код цих обчислень або операцій можна вставити одразу після успішного виклику fork(), і вони будуть виконуватись в новому процесі аж до виклику функції exit() або _exit().

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