Fixes in lab1

This commit is contained in:
Andrew Golovashevich 2024-10-11 13:32:18 +03:00
parent 25b4284d09
commit d037c502b1
2 changed files with 98 additions and 14 deletions

47
lab1/questions.md Normal file
View File

@ -0,0 +1,47 @@
## Что такое процесс в контексте операционной системы? Чем процесс отличается от потока?
Изолированный набор ресурсов (потоков, страниц памяти, дескрипторов).
## Что такое системный вызов в контексте операционной системы?
Обращение к ядру.
## Что такое POSIX?
POSIX (англ. Portable Operating System Interface — переносимый интерфейс операционных систем) — набор стандартов,
описывающих интерфейсы между операционной системой и прикладной программой (системный API),
библиотеку языка C и набор приложений и их интерфейсов.
Стандарт создан для обеспечения совместимости различных UNIX-подобных операционных систем и переносимости
прикладных программ на уровне исходного кода, но может быть использован и для не-Unix систем.
## Какой системный вызов используется для создания нового процесса в Linux?
fork (57)
## Что такое идентификатор процесса (PID), и как его можно получить в программе на языке C?
Уникальное число, используемое для идентификации процесса.
```c
pid_t getpid(void);
```
## Какой системный вызов позволяет родительскому процессу ожидать завершения своего потомка, и как он работает?
`waitpid` - переводит вызывающий поток в спящее состояние, до тех пор пока вызывающий процесс не получит `SIGCHLD` с соответствующим `PID`.
## Что произойдет, если родительский процесс завершится раньше своих потомков? Как это отразится на процессе потомков в операционной системе Linux?
Родителем потомков станет процесс с `PID=1`.
## Как можно программно контролировать завершение процесса в бесконечном цикле с вероятностью завершения 1/3?
## Что делает системный вызов waitpid() и как его использовать для управления процессами в отношениях «родитель-потомок»?
## Что происходит, если вызвать waitpid() с флагом WNOHANG, и чем это отличается от вызова без этого флага?
С флагом `WHOHANG` функция сразу вернёт значение, без флага заблокирует вызывающий поток до завершения запрошенного процесса.
## Как можно использовать системный вызов sleep() для организации пауз между выполнением операций в процессе?
## В чем отличие между системными вызовами fork() и exec(), и как они используются при работе с процессами?
## Как можно использовать команды ps или top для мониторинга состояния процессов в Linux и анализа их поведения?

View File

@ -2,7 +2,9 @@
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <signal.h> #include <signal.h>
#include <sys/wait.h>
// Global variable with data, needed to communicate with another process.
struct ping_pong_data_t { struct ping_pong_data_t {
char const *name; char const *name;
pid_t pid_to_print; pid_t pid_to_print;
@ -10,32 +12,42 @@ struct ping_pong_data_t {
double delay_seconds; double delay_seconds;
} ping_pong_data; } ping_pong_data;
// Signal handler for printing PID and sending signal back to another process.
void do_ping_pong(int signo) { void do_ping_pong(int signo) {
if (signo != SIGUSR1) if (signo != SIGUSR1) // Protecting from unexpected signals
return; return;
// Printing some useful info
printf("[%s] Got signal\n", ping_pong_data.name); printf("[%s] Got signal\n", ping_pong_data.name);
printf("[%s] Another side PID=%d\n", ping_pong_data.name, ping_pong_data.pid_to_print); printf("[%s] Another side PID=%d\n", ping_pong_data.name, ping_pong_data.pid_to_print);
// Sleeping to avoid unreadable spam
printf("[%s] Sleeping %lf seconds before sending signal\n", ping_pong_data.name, ping_pong_data.delay_seconds); printf("[%s] Sleeping %lf seconds before sending signal\n", ping_pong_data.name, ping_pong_data.delay_seconds);
usleep((useconds_t) (1000 * 1000 * ping_pong_data.delay_seconds)); usleep((useconds_t) (1000 * 1000 * ping_pong_data.delay_seconds));
// Sending signal back
printf("[%s] Sending signal\n", ping_pong_data.name); printf("[%s] Sending signal\n", ping_pong_data.name);
kill(ping_pong_data.pid_to_send, SIGUSR1); kill(ping_pong_data.pid_to_send, SIGUSR1);
} }
// Global flag to stop infinite loop on interrupt (Ctrl+C)
volatile int is_running = 1; volatile int is_running = 1;
// Interrupt (Ctrl+C) handler
void interrupt(int signo) { void interrupt(int signo) {
if (signo != SIGINT) if (signo != SIGINT) // Protecting from unexpected signals
return; return;
kill(ping_pong_data.pid_to_send, SIGINT);
is_running = 0; is_running = 0;
} }
// Entry point
int main(void) { int main(void) {
signal(SIGINT, interrupt); // Obtaining PID of parent (main) process
pid_t parent_pid = getpid(); pid_t parent_pid = getpid();
// Obtaining PID of child (forked) process
pid_t child_pid = fork(); pid_t child_pid = fork();
@ -44,37 +56,62 @@ int main(void) {
perror("Failed to fork\n"); perror("Failed to fork\n");
return EXIT_FAILURE; return EXIT_FAILURE;
case 0: case 0:
// Obtaining PID of child (forked) process because fork() didn't return it
child_pid = getpid(); child_pid = getpid();
// Initializing settings
ping_pong_data.name = "\033[36mchild\033[0m"; ping_pong_data.name = "\033[36mchild\033[0m";
ping_pong_data.delay_seconds = 1.5; ping_pong_data.delay_seconds = 1.5;
ping_pong_data.pid_to_print = parent_pid; ping_pong_data.pid_to_print = parent_pid;
ping_pong_data.pid_to_send = parent_pid; ping_pong_data.pid_to_send = parent_pid;
// Debug info printing
printf("[%s] My PID=%d\n", ping_pong_data.name, getpid()); printf("[%s] My PID=%d\n", ping_pong_data.name, getpid());
// Initializing interruption (Ctrl+C) handler
signal(SIGINT, interrupt);
// Initializing communication handler
signal(SIGUSR1, do_ping_pong); signal(SIGUSR1, do_ping_pong);
break; // Eventloop
while (is_running)
pause();
// Notification about execution finishing
printf("[%s] Interrupted\n", ping_pong_data.name);
return EXIT_SUCCESS;
default: default:
// Initializing settings
ping_pong_data.name = "\033[31mparent\033[0m"; ping_pong_data.name = "\033[31mparent\033[0m";
ping_pong_data.delay_seconds = 1.5; ping_pong_data.delay_seconds = 1.5;
ping_pong_data.pid_to_print = child_pid; ping_pong_data.pid_to_print = child_pid;
ping_pong_data.pid_to_send = child_pid; ping_pong_data.pid_to_send = child_pid;
// Debug info printing
printf("[%s] My PID=%d\n", ping_pong_data.name, getpid()); printf("[%s] My PID=%d\n", ping_pong_data.name, getpid());
// Initializing interruption (Ctrl+C) handler
signal(SIGINT, interrupt);
// Initializing communication handler
signal(SIGUSR1, do_ping_pong); signal(SIGUSR1, do_ping_pong);
// Sending initial signal to start communication chain
kill(parent_pid, SIGUSR1); kill(parent_pid, SIGUSR1);
break;
}
// Eventloop
while (is_running) while (is_running)
pause(); pause();
// Notification about execution finishing
printf("[%s] Interrupted\n", ping_pong_data.name); printf("[%s] Interrupted\n", ping_pong_data.name);
// Releasing zombie-process
waitpid(child_pid, NULL, 0);
return EXIT_SUCCESS; return EXIT_SUCCESS;
}
} }