Část 1: Zjištění základních atributů (PID, PPID, UID)
Každý proces má své unikátní PID a identitu uživatele (UID). Než začneme procesy vytvářet, naučíme se zjistit data o procesu, ve kterém náš program právě běží.
K tomu použijeme systémová volání getpid() (vlastní ID), getppid() (ID rodičovského procesu) a getuid() (ID uživatele, pod kterým proces běží).
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
// Získáme atributy současného procesu
pid_t my_pid = getpid();
pid_t parent_pid = getppid();
uid_t my_uid = getuid();
printf("[Hlavní proces] Moje PID: %d\n", my_pid);
printf("[Hlavní proces] PID mého rodiče (PPID): %d\n", parent_pid);
printf("[Hlavní proces] Moje uživatelské UID: %d\n", my_uid);
return 0;
}
Část 2: Vytvoření nového procesu pomocí fork()
Nové procesy dědí atributy ze svého rodičovského (parent) procesu. V Linuxu se nový proces vytváří tak, že se ten stávající „rozdvojí“ pomocí volání fork().
Od okamžiku zavolání fork() běží v systému dva identické procesy (rodič a dítě). Rozlišíme je podle návratové hodnoty:
Rodič dostane jako výsledek PID svého nového dítěte.
Dítě dostane hodnotu
0.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
pid_t pid;
printf("Před rozdvojením (forkem)...\n");
// Rozdvojení procesu
pid = fork();
if (pid < 0) {
// Pokud fork selže
perror("Fork se nepovedl :(");
return 1;
}
else if (pid == 0) {
// Kód, který vykoná pouze DOSPĚLÉ DÍTĚ
printf("[Dítě] Já jsem nový proces! Moje PID je %d a PID mého rodiče je %d.\n", getpid(), getppid());
}
else {
// Kód, který vykoná pouze RODIČ
printf("[Rodič] Já jsem rodič. Moje PID je %d a vytvořil jsem dítě s PID %d.\n", getpid(), pid);
}
printf("[Proces %d] Tohle vypíší oba procesy, protože oba pokračují odsud dolů.\n", getpid());
return 0;
}
Část 3: Skupiny procesů a čekání na dítě (wait)
V této finální ukázce vytvoříme proces, zjistíme jeho skupinu pomocí getpgrp() a ukážeme si, jak rodič správně počká na ukončení svého dítěte pomocí volání wait(). Čekání je důležité, aby se z dítěte po skončení nestal tzv. „zombie proces“.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main() {
pid_t pid;
printf("[Rodič] Moje ID skupiny (PGID) je: %d\n", getpgrp());
pid = fork();
if (pid == 0) {
// Sme v dětském procesu
printf("[Dítě] Moje PGID je: %d (zdědil jsem ho od rodiče)\n", getpgrp());
printf("[Dítě] Teď budu 2 sekundy simulovat práci...\n");
sleep(2);
printf("[Dítě] Končím.\n");
return 42; // Dítě vrátí rodiči status 42
}
else {
// Jsme v rodiči
int status;
printf("[Rodič] Čekám, až dítě dokončí práci...\n");
// Rodič se zde zastaví a čeká na signál o konci dítěte
pid_t child_pid = wait(&status);
if (WIFEXITED(status)) {
printf("[Rodič] Dítě %d úspěšně skončilo a vrátilo kód: %d\n",
child_pid, WEXITSTATUS(status));
}
}
return 0;
}
Co jsme se naučili?
Jak zjistit identitu procesu (PID) a uživatele (UID).
Jak naklonovat proces pomocí
fork().Že procesy automaticky dědí skupinu (PGID) a rodič na ně musí počkat pomocí
wait().