fork()
crea un nuovo processo copiando il descrittore del processo. Quindi i due processi condividono (almeno inizialmente) alcuni dati, ma non appena un processo inizia a cambiare it, il meccanismo di copia su scrittura assicura che la modifica sia localizzata solo nel processo che l'ha effettivamente apportata. È il meccanismo standard per la generazione dei processi su UNIX.
Questo ovviamente crea una relazione genitore-figlio piuttosto naturale tra i processi, ma questo è indipendente dalla rappresentazione interna nel kernel. I descrittori di processo possono essere implementati come un elenco collegato, un albero, una tabella hash o qualsiasi altra struttura (più o meno) adatta. Tutto ciò di cui uno ha veramente bisogno è posto nel descrittore del processo del kernel che punta al processo genitore (e possibilmente anche ai processi figlio). Se è o non è utilizzato come parte fondamentale della struttura è una decisione progettuale. Una delle tante cose che entrano in gioco quando si decide una cosa del genere è per esempio cosa succede una volta che il processo padre esce - su UNIX il init
process adotta processi orfani (con tutti i processi figlio).
La tua confusione deriva dal mescolare due cose:(1) mantenere organizzati i descrittori del processo e (2) la relazione genitore/figlio.
Non è necessaria la relazione padre/figlio per decidere quale processo eseguire successivamente o (in generale) a quale processo inviare un segnale. Quindi, Linux task_struct
(che ho trovato in linux/sched.h
per i sorgenti del kernel 3.11.5) ha:
struct task_struct __rcu *real_parent; /* real parent process */
struct task_struct __rcu *parent; /* recipient of SIGCHLD, wait4() reports */
/*
* children/sibling forms the list of my natural children
*/
struct list_head children; /* list of my children */
struct list_head sibling; /* linkage in my parent's children list */
Hai ragione, esiste una struttura ad albero per la relazione figlio/genitore, ma sembra essere nascosta in un altro elenco e un puntatore al genitore.
Il famoso elenco a doppio collegamento non è ovvio nel struct task_struct
3.11.5 definizione della struttura. Se ho letto correttamente il codice, l'elemento struct non commentato struct list_head tasks;
è l'elenco a doppio collegamento "organizzativo", ma potrei sbagliarmi.