
- •6.050101 «Комп’ютерні науки»
- •Загальні вимоги до виконання лабораторних робіт
- •Лабораторна робота №1
- •1. Основні теоретичні відомості
- •1.1 Основні поняття
- •1.2 Створення процесу
- •1.3 Створення потоку
- •2. Хід роботи
- •4. Завдання
- •5. Контрольні запитання
- •6.Список використаної літератури
- •Додаток 1
- •Додаток 2
- •Додаток 3
- •Функція CreateProcess створює новий процес.
- •Додаток 4
- •Додаток 5
- •Addr ThreadId – Створює новий потік.
- •Додаток 6
- •Додаток 7
- •Лабораторна робота №2
- •1. Основні теоретичні відомості
- •1.1 Механізми міжпроцесової взаємодії
- •1.2 Механізми синхронізації процесів та потоків
- •1.3 Об’єкти синхронізації
- •1.4 Очікуючі функції
- •1.5 Створення атома
- •1.6 Створення каналу
- •2. Хід роботи
- •4. Завдання
- •5. Контрольні запитання
- •6.Список використаної літератури
- •Додаток 1
- •Додаток 2
- •Додаток 3
- •Додаток 4
- •Додаток 5 Детальний опис функції створення анонімного каналу
- •Додаток 6 Детальний опис функції створення іменованого каналу
- •Додаток 7
- •Додаток 8
- •Додаток 9 Текст програми створення анонімного каналу
- •Додаток 10
- •Лабораторна робота №3
- •1. Основні теоретичні відомості
- •2. Приклад програми створення dll
- •Опис програми My_dll.Asm та файлу лістінга My_dll.Def
- •4. Трансляція та компонування dll Для того, щоб відтранслювати(ml.Exe) та зкомпонувати (link.Exe) даний .Asm код, потрібно використовувати наступні параметри:
- •5. Приклад використання функції з бібліотеки
- •Приклад програми завантаження dll
- •7. Створення файлу лістінгу існуючої бібліотеки
- •8. Приклад передачі даних у функцію бібліотеки Створення динамічно завантажуваної бібліотеки
- •Передача параметру у функцію бібліотеки
- •9. Хід роботи
- •11. Завдання
- •12. Контрольні запитання
- •13. Список використаної літератури
- •Лабораторна робота №4
- •1. Основні теоретичні відомості
- •Параметри функції CreateToolhelp32Snapshot:
- •2. Перегляд процесів
- •3. Перегляд потоків
- •Значення результуючого параметру (регістр еах) таке саме як в Process32First і Process32Next.
- •4. Перегляд хіпів асоційованих з процесом
- •5. Перегляд модулів, які використовує процес
- •6. Керування процесами
- •7. Хід роботи
- •9. Завдання На 75 балів виконати 4 завдання:
- •10. Контрольні запитання
- •11. Список використаної літератури
- •Додаток 1
- •Лабораторна робота №5
- •Основні теоретичні відомості
- •1.1 Основні поняття
- •1.2 Категорії даних
- •1.3 Відкриття і закриття ключів реєстру
- •1.4 Створення підключа у відкритому ключі реєстру
- •1.5 Отримання інформації з ключа реєстру
- •1.6 Перелічення списку значень для заданого ключа реєстру
- •1.7 Виявлення змін в гілці реєстру
- •1.8 Робота з налаштуваннями операційної системи через реєстр
- •2. Хід роботи
- •4. Завдання
- •5. Контрольні запитання
- •6. Список використаної літератури
- •Додаток 1
- •Лабораторна робота №6
- •1. Основні теоретичні відомості
- •Породження процесів
- •1.2 Породження потоків
- •2. Хід роботи
- •4. Індивідуальні завдання
- •5. Контрольні запитання
- •Для нотаток Для нотаток Для нотаток
Додаток 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. Основні теоретичні відомості
Породження процесів
Звичайно, новий процес в 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().