Hlavičkový obrázek pro články C/C++

Spouštění procesů v C

Motivací k programování víceprocesových aplikací může být několik. V dřívějších dobách, kdy počítače ještě neměly potřebný výkon, bylo možné spustit vždy pouze jeden proces. Uživatel proto musel vždy čekat, než se mu například stáhne obsah diskety na disk, aniž by mohl dělat cokoliv jiného, než pozorovat, jak se kopíruje. Tato doba už je naštěstí dávno pryč a nyní je možné dělat celou řadu jiných a lepších aktivit během kopírování.

Po spuštění standardní aplikace napsané v C, běží aplikace jako jeden proces. Každé čtení/zápis do paměti proto zastaví celou aplikaci. Aby jsme se tomu předešli můžeme aplikaci takzvaně rozvětvit. K rozvětvení aplikace slouží systémové volání obstarané funkcí fork() z knihovny unistd.h. Po zavolání fork() vzniknout dva totožné procesy, každý ale s jiným PID. Tyto dva procesy se začnou vykonávat paralelně od místa, kde bylo voláno fork(), budou tedy vykonávat stejný program.

Ukázka jednoduchého zavolání fork(). Program do terminálu dvakrát vypíše Job completed.

#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv){
	fork();
	printf("Job completed\n");

	return 0;
}

Aby rozvětvení do dvou procesů provedlo něco smysluplnějšího, než pouhé dvojí provedení jedné úlohy, je potřeba rozlišit, zda se část úlohy vykonává v rodiči, nebo v potomku. Volání fork() má jako návratovou hodnotu PID procesu (potomka), který právě vytvořilo. Pokud se programu z nějakého důvodu nepovede rozvětvení, vrátí jako PID potomka -1. Když si tuto hodnotu zapamatujeme, můžeme podle ní pak zjistit, zda kód vykonává rodič, nebo potomek.

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(int argc, char **argv){
	pid_t child_pid;

	/* Fork program to module can download status */
	child_pid = fork();
	if(child_pid != 0){
		printf("This is parent process with pid: %d\n", (int)getpid());
	} else if(child_pid == -1){
                printf("Cannot fork\n");
                return -1;
        } else {
		printf("This is child process with pid: %d\n", (int)getpid());
                /* Provede něco časově náročného */
 		return 0;
        }

	printf("Job completed\n");

	return 0;
}

Protože rodič má v proměnné child_pid uložený PID svého potomka, lze podle toho rozhodnout, zda se program vykonává v rodiči/potomkovi. Vzhledem k tomu, že při rozvrhování procesů není zaručeno pořadí, v jakém se vykonávají (ve skutečnosti se každý vykonává chvíli) je zde možnost více pořadí ve výstupu programu. Program by ale měl například vypsat:

This is parent process with pid: 1853
This is child process with pid: 1854
Job completed

 


Posted

in

by

Tags: