Національний університет «Львівська політехніка»
Інститут комп’ютерних технологій, автоматики та метрології
ІКТА
Кафедра БІТ
Звіт
Лабораторна робота № 4
«Робота з процесами в ОС Linux»
Варіант – 14
Львів 2018
Мета роботи: Оволодіти практичними навичками роботи з процесами в ОС Linux. Ознайомитись із механізмом створення, розгалуження, виконання та завершення процесів в Linux. Ознайомитись із ієрархією процесів та навчитись створювати групи процесів.
Теоретичні відомості
Управління процесами в ОС Linux
Процеси - це одна з найбільш фундаментальних абстракцій (після файлів) в UNIX-подібних операційних системах. Якщо розглядати процеси як об'єкт виконуваного коду - живої, активної, програми, що працює – вони є чимось більшим, ніж набір асемблерних інструкцій, і складаються з даних, ресурсів, внутрішнього стану процесора. Ми розглянемо головні складові процесу, від створення до завершення.
Принципи які були закладені при проектуванні UNIX, з часом майже не змінились. Особливо це видно в управлінні процесами, саме тут проявляється далекоглядність і довговічність початкової концепції UNIX. Так в концепції UNIX створення нового процесу відділяється від завантаження нового бінарного образу. Хоча в більшості випадків ці дії виконуються спільно, поділ дозволяє експериментувати і відкриває широкі можливості для розвитку кожної задачі. Таким чином, ця концепція (яка доволі рідко зустрічається) збереглася до наших днів, в той час як більшість операційних систем пропонують один системний виклик для запуску однієї програми, в UNIX потрібні два: fork і ехес. Проте до вивчення цих системних викликів давайте детально розглянемо сам процес.
Програми, процеси і потоки
Бінарний модуль - це скомпільований, виконуваний код, що знаходиться в якому-небудь сховищі даних, наприклад на диску. Також, ми можемо використовувати термін «програма»; великі й значні бінарні модулі можна називати додатками. І /bin/ls і /usr/bin/X11 є бінарними модулями. Процесом є запущена програма. Процес включає в себе бінарний образ, що завантажується в пам'ять, і багато іншого: віртуальну пам'ять, ресурси ядра, наприклад відкриті файли, а також запуск одного або декількох потоків. Потік - це одна з дій всередині процесу. Кожен потік має власний віртуальний процесор, що включає в себе стек, стан процесора, наприклад регістри, а також командні покажчики.
Якщо в процесі потік тільки один, то процес і є потоком, у нього тільки один екземпляр віртуальної пам'яті і один віртуальний процесор. В багатопоточних процесах потоків декілька. Віртуальна пам'ять зв’язана з процесом, тому всі потоки одночасно використовують один і той самий адресний простір пам'яті.
Ідентифікатор процесу
Кожен процес позначається унікальним ідентифікатором (Process ID, зазвичай скорочується до PID). PID обов'язково є унікальним в будь-який конкретний момент часу. Це означає, що в момент часу T0 може бути тільки один процес з PID 770 (або жодного процесу з таким значенням ідентифікатора), але не гарантується, що в момент часу T1 не буде існувати іншого процесу з тим же ідентифікатором PID 770.
Пасивний процес, який виконується ядром при відсутності всіх інших процесів, має PID 0. Перший процес, який ядро виконує під час запуску системи, називається процесом ініціалізації і має PID 1. Зазвичай init process в Linux є програмою ініціалізації. Ми використовуємо термін «ініціалізація» для позначення початкового процесу, що запускається при завантаженні, та спеціальної програми, яка використовується для цихцілей. Після запуску процес ініціалізації виконує решту завантаження. Як правило, в нього входять ініціалізація системи, запуск різних сервісів і програми авторизації.
Завдання:
Варіант – 14
В програмі на мові С поточний процес повинен створити дочірній процес та вивести його ідентифікатор. Дочірній процес виводить ір адресу комп’ютера та arp таблицю. Завершити процеси та здійснити обробку помилок.
Хід роботи
Текст програми:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cpuid.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <ifaddrs.h>
#include <netdb.h>
#define xstr(s) str(s)
#define str(s) #s
#define ARP_CACHE "/proc/net/arp"
#define ARP_STRING_LEN 1023
#define ARP_BUFFER_LEN (ARP_STRING_LEN + 1)
/* Format for fscanf() to read the 1st, 4th, and 6th space-delimited fields */
#define ARP_LINE_FORMAT "%" xstr(ARP_STRING_LEN) "s %*s %*s " \
"%" xstr(ARP_STRING_LEN) "s %*s " \
"%" xstr(ARP_STRING_LEN) "s"
int main(int argc, char *argv[]) {
pid_t pid;
int rv;
int n;
struct ifreq ifr;
char array[] = "eth0";
FILE *arpCache = fopen(ARP_CACHE, "r");
if (!arpCache)
{
perror("Arp Cache: Failed to open file \"" ARP_CACHE "\"");
return 1;
}
/* Ignore the first line, which contains the header */
char header[ARP_BUFFER_LEN];
if (!fgets(header, sizeof(header), arpCache))
{
return 1;
}
char ipAddr[ARP_BUFFER_LEN], hwAddr[ARP_BUFFER_LEN], device[ARP_BUFFER_LEN];
int count = 0;
while (3 == fscanf(arpCache, ARP_LINE_FORMAT, ipAddr, hwAddr, device))
{
printf("%03d: Mac Address of [%s] on [%s] is \"%s\"\n",
++count, ipAddr, device, hwAddr);
}
fclose(arpCache);
switch(pid=fork()) {
case -1:
perror("fork");
exit(1);
case 0:
if (pid != -1) {
pid = getpid();
printf("PID of this proccess is %ld\n",pid);
switch(pid = fork()) {
case -1:
perror("2nd fork");
exit(1);
case 0:
if (pid != -1) {
n = socket(AF_INET, SOCK_DGRAM, 0);
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name , array , IFNAMSIZ - 1);
ioctl(n, SIOCGIFADDR, &ifr);
close(n);
printf("IP Address is %s - %s\n" , array , inet_ntoa(( (struct sockaddr_in *)&ifr.ifr_addr )->sin_addr) );
}
default:
wait(pid);
}
}
exit(rv);
default:
wait(pid);
WEXITSTATUS(rv);
printf("Exit from PARENT!\n");
}
}
Виконання роботи:
/
/
Висновок: Оволодів практичними навичками роботи з процесами в ОС Linux. Ознайомився із механізмом створення, розгалуження, виконання та завершення процесів в Linux. Ознайомився із ієрархією процесів та навчився створювати групи процесів.