Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

esercizio fork()

Linguaggi e sistemi

Moderatori: Foto UtentePaolino, Foto Utentefairyvilje

0
voti

[1] esercizio fork()

Messaggioda Foto Utentemarc96 » 29 gen 2019, 21:31

Sono alle prese con il seguente esercizio sulla fork():
Codice: Seleziona tutto
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(){
  int ret1=0,ret2=0,ret3=0;
  printf ("[%d],%d,%d,%d\n", getpid (),ret1,ret2,ret3);
  (ret1=fork()) && (ret2=fork()) || (ret3=fork());
  wait();
  printf ("[%d],%d,%d,%d\n", getpid (), ret1, ret2, ret3);
}


Ho eseguito su due compilatori online:
su onlinegdb.com
ho come risposta
[5],0,0,0
[8],6,0,0
[7],6,0,8
[5],6,7,0
[9],0,0,0
[6],0,0,9

Mentre su ideone.com
ho come risposta
[15201],0,0,0
[15344],15342,0,0
[15201],0,0,0
[15343],15342,0,15344
[15201],0,0,0
[15201],15342,15343,0
[15201],0,0,0
[15345],0,0,0
[15201],0,0,0
[15342],0,0,15345

Quindi 6 stampe contro 10.
Guardando bene, nell'out di ideone.com si ripetono ben 4 out identici
[15201],0,0,0
che secondo me non ci dovrebbero stare, almeno credo, in quanto si riferiscono al processo padre iniziale.
Il resto dell'out lo comprendo (permette di capire come i diversi processi vengono eseguiti temporalmente) e i due compilatori forniscono lo stesso risultato, a parte l'id dei processi.
Ho eseguito più volte e l'out è risultato sempre lo stesso.

Avete una spiegazione per questi 4 out [15201],0,0,0 che non riesco a capire?
Grazie.
Ultima modifica di Foto Utentemarc96 il 29 gen 2019, 21:40, modificato 1 volta in totale.
Avatar utente
Foto Utentemarc96
299 1 8
Frequentatore
Frequentatore
 
Messaggi: 198
Iscritto il: 16 ott 2011, 10:03

0
voti

[2] Re: esercizio fork()

Messaggioda Foto Utenterugweri » 29 gen 2019, 21:36

Il codice va messo entro i tag [code]: il regolamento lo prevede, e tra l'altro è assurdo (e, permettimi, anche un po' maleducato) aspettarsi che qualcuno legga del codice non formattato.
Avatar utente
Foto Utenterugweri
5.948 2 8 13
CRU - Account cancellato su Richiesta utente
 
Messaggi: 1366
Iscritto il: 25 nov 2016, 18:46

1
voti

[3] Re: esercizio fork()

Messaggioda Foto Utentemarc96 » 29 gen 2019, 21:41

Mi scuso, spero di aver modificato bene.
Avatar utente
Foto Utentemarc96
299 1 8
Frequentatore
Frequentatore
 
Messaggi: 198
Iscritto il: 16 ott 2011, 10:03

1
voti

[4] Re: esercizio fork()

Messaggioda Foto Utentexyz » 29 gen 2019, 23:16

Trascurando la pessima formattazione del codice, quel codice ha poco senso. In C le operazione booleane sono ottimizzate dal compilatore compresa la sequenza di valutazione e come è scritta dipende molto dalla velocità con cui lo scheduler risponde e su come assegna i processi in base al hardware disponibile.

La funzione "wait" senza parametro non sono riuscito a trovarla (Linux kernel 4.18.17) quindi il linker molto probabilmente utilizza la funzione con un parametro il quale è indeterminato. Se si aggiunge l'include "sys/wait.h" il compilatore segnala giustamente l'errore per la mancanza del parametro.
Avatar utente
Foto Utentexyz
6.864 2 4 6
G.Master EY
G.Master EY
 
Messaggi: 1778
Iscritto il: 5 dic 2009, 18:37
Località: Italy Turin

0
voti

[5] Re: esercizio fork()

Messaggioda Foto Utentemarc96 » 30 gen 2019, 0:09

Innanzitutto grazie per la risposta.
Che il codice non abbia senso è sicuro, ma chiedilo a chi assegna questi esercizi in una università italiana. Per fortuna non sono lo studente interessato (Ho da troppi anni superato quel periodo...)
Hai ragione sulla wait() senza argomento: a parte il fatto di come mai compilava senza l'include, ho inserito io questa funzione perché, usando la fork(),mi stabilizza l'out...(mi posso pure sbagliare). Ho trovato in rete anche wait(NULL).
Comunque ho ricompilato come mi suggerisci
Codice: Seleziona tutto
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
    int ret1=0,ret2=0,ret3=0, status;
    printf ("[%d],%d,%d,%d\n", getpid (),ret1,ret2,ret3);
    (ret1=fork()) && (ret2=fork()) || (ret3=fork());
    wait(&status);
    printf ("[%d],%d,%d,%d\n", getpid (), ret1, ret2, ret3);
}

Spero che la formattazione automatica di codeblocks sia accettabile, non so fare di meglio e non programmo da tanto tempo.
L'out però non è cambiato in entrambi gli ambienti e il dubbio iniziale rimane.
Avatar utente
Foto Utentemarc96
299 1 8
Frequentatore
Frequentatore
 
Messaggi: 198
Iscritto il: 16 ott 2011, 10:03

2
voti

[6] Re: esercizio fork()

Messaggioda Foto Utentexyz » 30 gen 2019, 2:05

Sorgente compilato col GCC con opzione di ottimizzazione "-O2".

L'output diretto:

Codice: Seleziona tutto
$> ./a.out
[6729],0,0,0
[6732],0,0,0
[6733],6730,0,0
[6730],0,0,6732
[6731],6730,0,6733
[6729],6730,6731,0

Se viene messo in pipe con un altro processo:

Codice: Seleziona tutto
$> ./a.out | tee
[6767],0,0,0
[6771],0,0,0
[6767],0,0,0
[6772],6769,0,0
[6767],0,0,0
[6769],0,0,6771
[6767],0,0,0
[6770],6769,0,6772
[6767],0,0,0
[6767],6769,6770,0

La pipe crea dei buffer temporanei per lo stdin e stdout per sincronizzare output.

Se si disattivano i buffer le cose ritornano come nel primo esempio:

Codice: Seleziona tutto
$> unbuffer ./a.out | tee
[7836],0,0,0
[7844],0,0,0
[7845],7842,0,0
[7842],0,0,7844
[7843],7842,0,7845
[7836],7842,7843,0


Ordine delle righe può cambiare in base al carico della CPU nel momento dell'esecuzione del comando.

P.S. Qui viene spiegato cosa succede quando si valuta l'espressione booleana con i valori di ritorno della fork:

https://www.geeksforgeeks.org/fork-and-binary-tree/
Avatar utente
Foto Utentexyz
6.864 2 4 6
G.Master EY
G.Master EY
 
Messaggi: 1778
Iscritto il: 5 dic 2009, 18:37
Località: Italy Turin

0
voti

[7] Re: esercizio fork()

Messaggioda Foto Utentemarc96 » 30 gen 2019, 9:54

grazie, sei gentilissimo. studio...
Avatar utente
Foto Utentemarc96
299 1 8
Frequentatore
Frequentatore
 
Messaggi: 198
Iscritto il: 16 ott 2011, 10:03


Torna a PC e informatica

Chi c’è in linea

Visitano il forum: Nessuno e 27 ospiti