PDA

View Full Version : [C Unix]: Fork(), Pid e chiamate


zanardi84
24-03-2009, 14:57
Sto cercando di capire, senza successo purtroppo, come funziona la creazione dei processi figli a partire da un processo padre.

Esempio preso da una slide

#include <stdio.h>
#include <sys/types.h>
void main()
{ pid_t pid;
printf (“Prima della fork: PID = %d\n”, getpid());
pid = fork();
if (pid==0) /* PROCESSO FIGLIO*/
{printf (“FIGLIO: PID = %d\n”, getpid());
exit(0);
}
else /* PROCESSO PADRE */
{printf (“PADRE: PID = %d\n”, getpid());
printf (“PADRE: PID DEL FIGLIO = %d\n”, pid);
exit(0);
}
}

Come funziona?
La fork crea comunque il processo?
Come si stabilisce chi parte per primo dopo la fork? E in base a che criterio parte prima uno o l'altro?

pid: come cambia il suo valore? Perchè a un certo punto ho il valore del padre, poi diventa zero e poi diventa quello del figlio? Il valore zero è solo temporaneo?

fero86
24-03-2009, 17:05
Come si stabilisce chi parte per primo dopo la fork? i moderni sistemi di derivazione Unix in genere sono concorrenti, quindi idealmente i due processi ripartono tutti e due contemporaneamente; o addirittura possono partire effettivamente in contemporanea se vengono schedulati su due core differenti.


pid: come cambia il suo valore? non cambia: ad ogni processo viene associato un identificatore unico durante la creazione e quello rimane; al processo padre resta il PID associatogli quando é partito e al processo figlio viene associato un nuovo PID generato durante la creazione del processo causata dalla fork.


Perchè a un certo punto ho il valore del padre, poi diventa zero e poi diventa quello del figlio? Il valore zero è solo temporaneo? non ho letto il codice ma considera questi due fattori:
1) lo zero non é un vero PID, é solo un valore restituito dalla fork al processo figlio per fargli capire che lui é il processo figlio (al padre invece viene ritornato il PID del figlio);
2) quando viene creato un processo figlio questo gira concorrentemente col padre e i due usano in concorrenza gli stessi standard stream; ció non é sbagliato perché le scritture sui file descriptors sono atomiche per piccole quantitá di dati (vedi la documentazione della syscall write), ma significa che i due processi fanno output sullo stesso terminale.

PS: non mi andava di leggere il codice :D

sirus
24-03-2009, 19:50
Sto cercando di capire, senza successo purtroppo, come funziona la creazione dei processi figli a partire da un processo padre.

Come funziona?
La fork crea comunque il processo?
Come si stabilisce chi parte per primo dopo la fork? E in base a che criterio parte prima uno o l'altro?

pid: come cambia il suo valore? Perchè a un certo punto ho il valore del padre, poi diventa zero e poi diventa quello del figlio? Il valore zero è solo temporaneo?
A meno di errori dovuti alla chiamata della funzione fork() (che il codice che hai postato non gestisce), la fork() genera sempre un nuovo processo.
Semplificando il processo, il sistema operativo copia la "memoria" del padre sulla "memoria" del figlio. Da quel momento ogni processi ha una sua evoluzione e può ovviamente avere valori differenti per la stessa variabile, a te sembra che le variabili cambino valore, in realtà sono variabili diverse perché appartengono a processi diversi.
Ho semplificato pesantemente il tutto, se stai seguendo un corso otterrai sicuramente informazioni più dettagliate in futuro.

WarDuck
25-03-2009, 19:03
Premesso che il codice che eseguono i due processi parte da dopo la chiamata fork (so che a qualcuno può sembrare banale, ma comincia a non esserlo più se vi chiedete quanti processi vengono creati in un ciclo for con 2 fork), cmq è lo scheduler del sistema operativo che si occupa di scegliere quale processo porre in stato di esecuzione.

In genere cmq il sistema è basato su code di priorità.

Ogni processo parte con una priorità k e si pone nella sua coda k, lo scheduler tipicamente sceglierà il primo elemento nella coda k più alta.

La priorità è dinamica quindi può cambiare durante il corso dell'esecuzione di un programma.

In ogni caso si segue a parità di priorità un'approccio di tipo round robin per quanti di tempo, ovvero lo scheduler assegna ai vari processi in coda un quanto di tempo a turno.

sirus
25-03-2009, 20:07
Premesso che il codice che eseguono i due processi parte da dopo la chiamata fork (so che a qualcuno può sembrare banale, ma comincia a non esserlo più se vi chiedete quanti processi vengono creati in un ciclo for con 2 fork), cmq è lo scheduler del sistema operativo che si occupa di scegliere quale processo porre in stato di esecuzione.
L'esecuzione del processo figlio parte effettivamente dopo la chiamata della funzione fork() ma tutto il code segment viene copiato quindi è possibile che il processo figlio (ed ovviamente il padre) tornino ad eseguire parti di codice che precedono la fork().

In genere cmq il sistema è basato su code di priorità.

Ogni processo parte con una priorità k e si pone nella sua coda k, lo scheduler tipicamente sceglierà il primo elemento nella coda k più alta.

La priorità è dinamica quindi può cambiare durante il corso dell'esecuzione di un programma.

In ogni caso si segue a parità di priorità un'approccio di tipo round robin per quanti di tempo, ovvero lo scheduler assegna ai vari processi in coda un quanto di tempo a turno.
Questo è in realtà una breve spiegazione di un process scheduler di tipo multilivello (attualmente utilizzato da Windows). Linux ne faceva uso in passato, ora il process scheduler è piuttosto differente.

_Claudio
25-03-2009, 21:54
Dai una googlata riguardo il Process Control Block che quasi tutti lo ignorano ma è un componente fondamentale e ti fa capire alla perfezione come funziona il meccanismo di schedulazione che, in una CPU monocore, in generale nell'immediato avvia un processo a caso. Ossia quando chiami fork() non si sa mai a priori chi va in esecuzione, a meno di una specifica del SO.

Non dimentichiamo le differenze tra processi e thread che a mio avviso rimangono fondamentali e su cui spesso si fa confusione.

WarDuck
26-03-2009, 08:22
L'esecuzione del processo figlio parte effettivamente dopo la chiamata della funzione fork() ma tutto il code segment viene copiato quindi è possibile che il processo figlio (ed ovviamente il padre) tornino ad eseguire parti di codice che precedono la fork().


Quindi dici che uno dei due potrebbe eseguire nuovamente una fork? Mi sembra un po' strano...


Questo è in realtà una breve spiegazione di un process scheduler di tipo multilivello (attualmente utilizzato da Windows). Linux ne faceva uso in passato, ora il process scheduler è piuttosto differente.

Hai qualche riferimento in merito allo scheduler di Linux? Sono curioso, perché avendo fatto un corso introduttivo di Sistemi Operativi ci hanno descritto la classica struttura a coda di priorità e quanti di tempo :D.

sirus
26-03-2009, 10:24
Quindi dici che uno dei due potrebbe eseguire nuovamente una fork? Mi sembra un po' strano...
Entrambi... :D è abbastanza che la fork() sia in un ciclo.

Hai qualche riferimento in merito allo scheduler di Linux? Sono curioso, perché avendo fatto un corso introduttivo di Sistemi Operativi ci hanno descritto la classica struttura a coda di priorità e quanti di tempo :D.
Lo scheduler attualmente implementato nel kernel vanilla è il Completely Fair Scheduler (CFS). ;)
Comunque anche nel "corso di OS" (le virgolette non sono state messe a caso :cry: ) che ho fatto io gli scheduler sono stati trattati velocemente e senza riferimento agli scheduler implementati dai sistemi operativi. :(

_Claudio
26-03-2009, 19:48
L'esecuzione del processo figlio parte effettivamente dopo la chiamata della funzione fork() ma tutto il code segment viene copiato quindi è possibile che il processo figlio (ed ovviamente il padre) tornino ad eseguire parti di codice che precedono la fork().


Assolutamente no, altrimenti si potrebbe avere un ciclo infinito...
La fork() sdoppia il PCB e assieme ad esso anche il valore del PC, quindi a meno che la fork non sia inserita in un ciclo...

Per quanto riguarda lo scheduling adottato da Linux basta andare a pagina 731 del Silberschatz...

sirus
26-03-2009, 19:51
Assolutamente no, altrimenti si potrebbe avere un ciclo infinito...
La fork() sdoppia il PCB e assieme ad esso anche il valore del PC, quindi a meno che la fork non sia inserita in un ciclo...
Ed io che ho scritto nel mio ultimo post? :asd:

Per quanto riguarda lo scheduling adottato da Linux basta andare a pagina 731 del Silberschatz...
A meno che il libro non sia molto recente dubito che le informazioni siano corrette visto e considerato che lo scheduler del kernel Linux è stato sostituito da "poco". ;)

_Claudio
26-03-2009, 20:07
Ed io che ho scritto nel mio ultimo post? :asd:


Errore mio... ho interpretato male in effetti.


A meno che il libro non sia molto recente dubito che le informazioni siano corrette visto e considerato che lo scheduler del kernel Linux è stato sostituito da "poco". ;)

Sul libro fa riferimento al kernel 2.5...

sirus
26-03-2009, 20:25
Sul libro fa riferimento al kernel 2.5...
Il ramo 2.5 era dedicato all'innovazione quando ancora il ramo 2.4 era utilizzato in produzione. Con il ramo 2.6 il modello di sviluppo che prevedeva un ramo "stabile" ed un ramo di "sviluppo" è stato abbandonato; direi che il libro è veramente molto datato.
Inoltre, con la versione 2.6.23 il process scheduler ha subito un cambiamento radicale (introduzione del CFS in luogo del O(1)). ;)

_Claudio
26-03-2009, 21:10
Il ramo 2.5 era dedicato all'innovazione quando ancora il ramo 2.4 era utilizzato in produzione. Con il ramo 2.6 il modello di sviluppo che prevedeva un ramo "stabile" ed un ramo di "sviluppo" è stato abbandonato; direi che il libro è veramente molto datato.
Inoltre, con la versione 2.6.23 il process scheduler ha subito un cambiamento radicale (introduzione del CFS in luogo del O(1)). ;)

Neanche tanto... è del 2006... certo, col passo che hanno le tecnologie...

Poi io sono ancora di più datato essendo un Winaro e usando linux sporadicamente e con la molletta al naso :D