Sistemioperativi ìfor.unipi.it/fabio_del_vigna/files/2016/09/Lezione_5.pdfpadre Fabio Del Vigna...

70
ì Fabio Del Vigna - [email protected] Sistemi operativi Corso di Laurea Triennale in Ingegneria Informatica Lezione 5 Programmazione concorrente Processi, fork Processi: Gestione, Priorità Comandi per gestire processi Pianificazione esecuzione

Transcript of Sistemioperativi ìfor.unipi.it/fabio_del_vigna/files/2016/09/Lezione_5.pdfpadre Fabio Del Vigna...

  • ì

    FabioDelVigna- [email protected]

    Sistemi operativiCorso di Laurea Triennale in Ingegneria Informatica

    Lezione 5• Programmazione concorrente• Processi, fork• Processi: Gestione, Priorità• Comandi per gestire processi• Pianificazione esecuzione

  • Domande sulle lezioni passate?

    FabioDelVigna- [email protected]

  • Soluzione esercizi passati

    ì Dautente (apartire dalla propria home)ì tarcvzf config.tgz /etc/*confì tarztvf config.tgzì gunzip config.tgzì tarxvf config.tar

    ì Daqualsiasi cartellaì find/etc/-name\*sys\*-size+10cì find/-perm-u=s-or-perm-g=sì find/-name\*tab\*-execcat{}+

    FabioDelVigna- [email protected]

  • Sommario

    ì Programmazioneconcorrente

    ì Processiì Operazionisuiprocessi

    ì Creazione,comunicazione,…ì Gestionedeiprocessiì Prioritàdeiprocessi(nice)ì Comandiperlagestionedeiprocessi(ps,top)

    ì Pianificazioneesecuzione

    FabioDelVigna- [email protected]

  • Programmazione concorrente

    ì Tecnicheestrumentipersupportarepiùattivitàsimultaneeinunaapplicazionesoftware.

    ì Caratteristicadeisistemimultiprogrammati.

    ì Consenteapiùutentidiaccederecontemporaneamente adunsistemainformatico

    ì Consenteadunsoloutentel'esecuzionedipiùprogrammisimultaneamente

    ì Consenteadunsingoloprogrammadiscomporrelapropriaattivitàinpiùattivitàconcorrenti

    FabioDelVigna- [email protected]

  • Programma vs Processo

    § Programma :entitàstaticacherimaneimmutatadurantel'esecuzione.Ècostituitodalcodiceoggettogeneratodallacompilazionedelcodicesorgente.

    § Processo :entitàutilizzatadalsistemaoperativoperrappresentareunaspecificaesecuzionediunprogramma.Èun'entitàdinamica,chedipendedaidatielaboratiedalleoperazionieseguite.Ilprocessoècaratterizzato:§ dalcodiceeseguibile§ dall'insiemeditutteleinformazionichenedefinisconolostato

    ð contenutodellamemoriaindirizzatað ithreadð idescrittorideifileedelleperifericheinuso.

    FabioDelVigna- [email protected]

  • Processi Unix

    FabioDelVigna- [email protected]

  • Processi

    ì Processi,sonoentitàchepossonocondividerecodice(secodicerientrante,inUnixèrientrante).

    ì Ilcodiceèrientrantesepuòesserecondivisoconaltriprocessi,senzacheessovengaalteratoesenonmodificaareedimemoriacondivisaovariabiliglobali

    FabioDelVigna- [email protected]

  • System call per i processi

    § Creazionediprocessi:fork()

    § Terminazione:exit()

    § Sospensioneinattesadellaterminazionedifigli:wait()

    § Sostituzionedicodiceedati:exec..()

    FabioDelVigna- [email protected]

  • Creazione di processi: fork() - 1

    § fork() consenteaunprocessodigenerareunprocessofiglio:§ Padreefigliocondividonolostessocodice§ Ilfiglioeredita unacopiadeidati(diutenteedikernel)delpadre

    FabioDelVigna- [email protected]

    padre

    figlio

    fork( )

  • Creazione di processi: fork() - 2

    int fork(void);

    § Lafork nonrichiedeparametri

    § Restituisceuninteroche:§ Perilprocessocreato(figlio)vale0§ Perilprocessopadre:

    ð Èunvalore>0cherappresentailPIDdelprocessofiglio

    ð Èunvalore<0incasodierrore

    FabioDelVigna- [email protected]

  • Relazione padre-figlio - fork()

    § Concorrenza:padreefiglioprocedonoinparallelo§ Ilcodiceècondiviso§ Lospaziodegliindirizzièduplicato:

    ð Ognivariabiledelfiglioèinizializzataconilvaloreassegnatoledalpadreprimadellafork()

    § Lauser structure èduplicata:ð Lerisorseallocatealpadreprimadellagenerazione

    sonocondivisecolfiglioð Stessagestionedeisegnaliperpadreefiglioð IlfiglionasceconlostessoProgramCounter delpadre:

    laprimaistruzioneeseguitaèquellachesegueimmediatamentelafork()

    FabioDelVigna- [email protected]

  • PPID e PID

    getpid()

    RestituisceilPIDdelprocesso

    getppid()

    RestituisceilPPIDdelprocesso,cioèilPIDdelprocessopadre

    FabioDelVigna- [email protected]

  • Terminazione di processi

    § Involontaria (tentativiazioniillegali)

    § Volontaria (esempiosyscall exit)

    § Terminazionedelprocesso:§ Seilprocessocheterminahafigliinesecuzione,ilprocessoinit adottaifigli

    § Seilprocessoterminaprimacheilpadrenerilevilostatoditerminazione(conwait)ilprocessopassaallostatozombie

    FabioDelVigna- [email protected]

  • Terminazione di processi - exit()

    void exit(int status);

    § Attraversoilparametrostatus ilprocessocheterminapuòcomunicarealpadreinformazionisulsuostatoditerminazione

    § Èsempreunachiamatasenzaritorno

    § Effettidiunaexit():§ Chiusuradeifileaperti§ Terminazionedelprocesso

    FabioDelVigna- [email protected]

  • Terminazione di processi - wait()

    ì int wait(int *status);

    § Lostatoditerminazionepuòessererilevatodalprocessopadre,mediantelasyscall wait():§ Ilparametrostatus èl'indirizzo dellavariabileincuivienememorizzatolostatoditerminazionedelfiglio

    § Ilrisultatodellawait èilpid delprocessoterminato,oppureuncodicedierrore(

  • Terminazione di processi - wait()

    ì Effettidellasyscall wait(& status):

    § Ilprocessochelachiamapuòaverefigliinesecuzione§ Setuttiifigli nonsonoancoraterminati,ilprocessosusospendeinattesadellaterminazionedelprimodiessi

    § Sealmenounfiglio ègiàterminatoedilsuostatononèancorastatorilevato(statozombie),lawait ritornaimmediatamente(statonellavariabilestatus)

    § Senonesisteneancheunfiglio,lawait nonèsospensivaeritornauncodicedierrore(

  • Sostituzione di codice - exec..()

    § Èpossibilesostituireilcodiceeseguitodaunprocessomedianteunasyscall dellafamigliaexec():

    execl(), execle(), execclp(), execv(), execve(), execvp(), ..

    § Effettoprincipalediunaexec..():ð Vengonosostituiticodiceedatidelprocessoche

    chiamalasyscall,concodiceedatidiunprogrammaspecificatocomeparametro

    FabioDelVigna- [email protected]

  • Sostituzione di codice - execl()

    ì int execl(char *pathname, char *arg0, ..., char *argN, (char*) 0);

    § pathname è il nome del file contenente il nuovo programma

    § arg0 è il nome del programma (argv[0])

    § arg1,...,argN sono gli argomenti da passare al programma

    § (char*) 0) è il puntatore nullo che termina la lista

    FabioDelVigna- [email protected]

  • Effetti dell'esecuzione di exec

    § Ilprocessodopol'exec():§ Mantienelastessaprocess structure (salvoleinformazionirelativealcodice)

    ð Stessopid,stessoppid (pid padre)§ Hacodice,datiglobali,stack eheap nuovi§ Riferisceunanuovatextstructure§ Mantieneuser area(apartePCeinformazionilegatealcodice)estack delkernel:

    ð Mantienelestesserisorseð Mantienelostessoenvironment (salvochesi

    usiexecle(), execve())

    FabioDelVigna- [email protected]

  • Esempio di fork() ed execl()

    #include #include #include int main (int argc, char * argv[]) {int pid, status;pid=fork();if (pid==0) {execl("/bin/ls", "ls", "-l", (char *) 0);printf("exec fallita!\n");exit(1);

    }else if (pid>0) {pid=wait(&status);

    /* Gestione dello stato */

    }else printf("fork fallita!\n");

    }

    FabioDelVigna- [email protected]

  • Codice nella cartella esempi

    §fork1.c§ Called once,returns twice

    §fork2.c§ Usodigetpid()egetppid()

    §exec1.c§ Usodiexecv (path ...)

    §fdtest1.c§ ReadeWritedaglistessifile

    FabioDelVigna- [email protected]

  • Codice nella cartella esempi

    §die1.c§ Padreterminaprimadelfiglio(./die)

    §die2.c§ Figlioterminaprimadelpadre(./die2&)

    §die3.c§ Signal handler inazione(./die3&)

    FabioDelVigna- [email protected]

  • Gestione dei processi

    FabioDelVigna- [email protected]

  • Processo

    § Processo:programmasingolonelmomentoincuivieneeseguito

    § Iprocessididividonoin:§ Utente§ Sistema

    FabioDelVigna- [email protected]

  • Stato di un processo

    § Creazione diunprocesso§ chiamata disistema fork()§ soltanto daunprocesso già attivo

    § Terminazione diunprocesso§ chiamata disistema exit()§ “zombie”:processo che hacompletato lasua esecuzione

    mache compareancora nella tabella dei processi (exitstatus)

    FabioDelVigna- [email protected]

  • init

    § init (/sbin/init) e’laradice dell’albero deiprocessi§ creato dalkernelalterminedelbootstrap

    § PID=1§ Nonhapadre

    § Seunprocesso termina i suoifigli diventano figli diinit

    FabioDelVigna- [email protected]

  • Identificazione dei processi

    § PID:identificatore univoco diprocesso

    § PGID:identificatore digruppo-processi

    § UID:identificatore diutente

    § GID:identificatore digruppo-utenti

    § PPID:ParentPID

    FabioDelVigna- [email protected]

  • PID

    § Numero a16bit(ditipo pid_t)assegnato sequenzialmentedalkernelperogni nuovo processo creato

    § >=0

    § Univoco

    § Riciclato quando termina

    § =0scheduler

    § =1init

    § =2pagedaemon

    FabioDelVigna- [email protected]

  • ID e privilegi

    § Aogni processo sono associati degli identificatori diutente (user-IDs)edigruppo (group-IDs)chedeterminano i suoi privilegi →quali systemcall ilprocesso hail diritto diinvocare esu quali risorse

    FabioDelVigna- [email protected]

  • Real ID

    § RUID eRGID:UIDeGIDdell’utente che hamandatoinesecuzione il processo§ Ivalori realuser-iderealgroup-idnoncambiano pertutta lasessione dilogin

    § soloroothail potere dicambiarli

    FabioDelVigna- [email protected]

  • Effective ID

    § EUID,EGID esupplementaryGID: UIDeGIDconsiderati perdeterminare i privilegi perl'accessoai file§ Possono noncoincidere conRUIDeRGIDseil fileeseguibile hail set-user-id(SUID) oil set-group-id(SGID) bitattivo

    § Possono variare durante l’esecuzione delprocesso

    FabioDelVigna- [email protected]

  • Meccanismo SUID/SGID

    § Ogni filehaunownereungroupowner

    § Seil filediunprogramma haattivo il bitdeipermessi SUID(SGID),allora l’EUID (EGID)diventaquello dell'owner (groupowner)delfile,quandoviene invocato conil comando exec.

    FabioDelVigna- [email protected]

  • setuid e setgid

    § int setuid(uid_t uid);§ int setgid(gid_t gid);

    § Cambiano realuser/groupIDed effectiveuser/groupID

    § Idempersetgidì NB:seinvocatodaunprocessoconIDdelsuper

    utente,unavoltacambiatoEUIDilprocessononpuòriacquisireiprivilegidiroot!

    FabioDelVigna- [email protected]

  • Utilizzo di EUID/EGID

    § Seunfilediprogramma appartiene alsuperuser edhail bitSUIDattivo,l'utente che lancia il programmaottiene i privilegi delsuperuser durante l'esecuzionedelprogramma stesso

    § Esempio →eseguibile passwd percambiare lapropria password:

    $ ls -l /usr/bin/passwd

    -r-s--x--x 1 root root 19336 Sep 7 2004 /usr/bin/passwd

    FabioDelVigna- [email protected]

  • FabioDelVigna- [email protected]

  • Get

    § pid_t getpid(void) : PID del processo

    § pid_t getppid(void) : PPID del processo

    § uid_t getuid(void) : RUID

    § uid_t geteuid(void) : EUID

    § gid_t getgid(void) : RGID

    § gid_t getegid(void) : EGID

    § Non possono fallire

    FabioDelVigna- [email protected]

  • Esempio

    #include int main(){

    uid_t uid, euid;gid_t gid, egid;uid = getuid();euid = geteuid();gid = getgid();egid = getegid();printf(“real uid: %d, effective uid:

    %d\n”,(int)uid,(int)euid);printf(“real gid: %d, effective gid:

    %d\n”,(int)gid,(int)egid);}

    FabioDelVigna- [email protected]

  • Priorità dei Processi

    FabioDelVigna- [email protected]

  • Priorità dei processi

    § Loscheduler UNIXorganizzal'esecuzionedeiprocessiinbaseallivellodipriorità.

    § Laprioritàvienecalcolatainbasea:§ tipodiprocesso§ comportamentodelprocesso§ variabileNICE.

    ps –l

    FabioDelVigna- [email protected]

  • Priorità

    § Priorità:§ 0– 99– PrioritàRealTime§ 100– 139– Prioritàperiprocessidell’utente§ -20e19– valoriassuntidanice§ Più altaèlapriorità→più “lentamente”vieneeseguitoilprocesso.

    § nice vienesommatanelcalcolodellapriorità.

    § L'utente(normaleoroot)nonpuòinterveniresullaprioritàmasolosulNICE

    FabioDelVigna- [email protected]

  • nice

    § Quando viene creato un nuovo processo, alla variabile NICE viene assegnato il valore di nicedel padre (di solito 0)

    § L'utente può richiedere una variazione con il comando nice.

    § L’utente (non root) può solo aumentare il NICE value.

    § Non è possibile ridurre un NICE value nemmenoper riportarlo al valore precedente da cui l’utente stesso lo ha elevato.

    FabioDelVigna- [email protected]

  • Super user e nice

    § Ilsuperuser puòinveceoperarenell'interocampoNICEesututtiiprocessidisistema

    Attenzioneaivalorinegativi!

    ì PR=20+NI

    PRsimappanell’intervallodipriorità100-139.AvoltesipuòtrovarecomePR=120+NI

    FabioDelVigna- [email protected]

  • Effetti di nice

    § SelavariabileNICEaumentailsuovaloreallorailprocessoeseguepiù lentamentealleggerendoilsistema.

    § Unusoappropriatoè quellodilanciareiprogrammiinbackgroundconunNICEelevato.

    FabioDelVigna- [email protected]

  • renice

    § Permette divariare il livello diNICEuna voltalanciato il processo

    § Unutentepuòapplicareilrenice soloaipropriprocessi.

    § renice accettaopzioniperspecificareiprocessinonsoloperPIDmaancheperutenteogruppodiprocessi.

    renice priority [[-p] pid] [[-g] pgrp] [[-u] user]

    FabioDelVigna- [email protected]

  • Esempio

    Lanciare il comando bzip2 inbackground

    $ bzip2 fileTantoGrande &

    Guardare il valore diNICE

    $ ps –xl

    Cambiare il livello diNICE

    $ renice valore PID

    Verificare il cambiamento

    FabioDelVigna- [email protected]

  • Comandi per la gestione dei Processi

    FabioDelVigna- [email protected]

  • ps (1 di 3)

    § ps :visualizzaiprocessiincorsodiesecuzione

    PIDTTSTATTIMECOMMAND32798p0Ss 0:00.03-bash(bash)32925p0R+0:00.00ps

    § PID:numerodelprocesso§ TT:terminale§ STAT:statodelprocesso

    FabioDelVigna - [email protected]

    • R : running• I : bloccato > 20s• S : bloccato < 20s• D : pausa non interrompibile• T : sospeso• Z : zombie• W : swappato• N : NICE > 0

  • ps (2 di 3) opzioni

    § x :visualizzaancheiprocessichenonprovengonodaterminali

    § u :indical’utenteacuiappartieneogniprocesso

    § a :visualizzaiprocessidituttigliutenti

    § O :mostraicampielencatidiseguito,più quelli didefault

    § o :precisale*sole*colonnedamostrare

    § U nome_utente :mostraiprocessidinome_utente

    FabioDelVigna- [email protected]

  • ps (3 di 3)

    § ps aux :indicatuttiiprocessiinesecuzioneUSER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMANDdaniel 32929 0.0 0.1 1484 944 p0 R+ 6:40PM 0:00.00 ps aux

    § VSZ:memoriavirtuale usata§ RSS:memoriafisica usata

    § VSZ>=RSS§ TT:terminale virtuale acui è associato

    § TT=??Processi nonassociati anessun terminale.Sonoi DEMONI, cioè processi disistema

    § STARTED:orario di partenza del processo§ TIME:tempototale incui hausato la CPU§ COMMAND:percorsochehacreatoilprocesso

    FabioDelVigna- [email protected]

  • top (1 di 3)

    § top :visionedinamicadeiprocessi§ load average :utilizzodellaCPUnell’ultimominuto,ultimi5e

    ultimi15§ CPUstate

    ð user :usatadagliutentið system :usatadallesystem callð interrupt:caricodatodalleinterruzionið nice :crescequandocambioNICEð idle :usatadalladummy()

    § Memð Totalð Usedð Sharedð Free

    FabioDelVigna- [email protected]

  • top (2 di 3)

    § PID§ USERNAME§ THR:thread§ PRI:prioritৠNICE§ SIZE:dimensioneinmemoriavirtuale§ RES:resident§ STATE§ TIME§ WCPU:mediaveloce§ COMMAND

    FabioDelVigna- [email protected]

  • top (3 di 3)

    § Comandiinterattivi§ h :help§ r :renice,chiedeilnuovolivello§ s :intervallodiaggiornamento§ k :segnale§ n :quantitàdiprocessidavisualizzare§ q :quit

    § Opzioni§ u nome_utente§ d secondi:intervallodiaggiornamento(default5s)

    FabioDelVigna- [email protected]

  • Pianificazione dei processi

    FabioDelVigna- [email protected]

  • Pianificazione dei processi

    § Esecuzioneindateeoraristabiliti§ Demonecron→controllaesecuzionipianificate

    § crontab:configurazionecron§ Solitamentesiha:

    § Unfileperogniutente§ Unogeneralepertuttoilsistema

    FabioDelVigna- [email protected]

  • cron

    ì Demone (inbackground)

    ì Filecrontab collocatiin

    § /etc/crontab

    § /var/cron/tabs/nome_utente

    FabioDelVigna- [email protected]

  • Comando crontab

    crontab [opzioni]

    § creareomodificarefilecrontab

    § Filecrontab usatidacron pereseguireicomandiindicati

    FabioDelVigna- [email protected]

    Solo root può agire sul file crontab di un altro utente

  • Opzioni al comando crontab

    [-u utente] file

    § Sostituisceilfilecrontab-l

    § Visualizzailfilecrontab-e

    § Creaomodificailfilecrontab-r

    § Cancellailfilecrontab

    FabioDelVigna- [email protected]

  • Variabili di ambiente

    § SHELL§ Qualeshell esegueicomandi(es./bin/sh)

    § MAILTO§ Destinatariodeimessaggi§ “” nonvieneinviatonessunmessaggio

    FabioDelVigna- [email protected]

  • Formato del file crontab

    23 0-23/2 * * * echo "Ciao"

    § campi separati daspaziature

    § istante diesecuzione§ minuto, ora, giorno, mese, giorno della settimana

    § utente§ soloper/etc/crontab

    § comando§ senza redirezione l’output viene inviato pere-mail

    FabioDelVigna- [email protected]

  • Caratteri speciali

    § * § qualsiasi valore

    § -§ delimitare valori (es.1-3)

    § , § separare singoli valori (es.2,5)

    § / § esprimere una granularità (es./8).Indica uno step

    temporale daseguire

    § Es:*/2 sulle oreesegue il comando ogni dueore

    FabioDelVigna- [email protected]

  • Esempio /var/cron/tabs/*

    # Utilizza «/bin/sh» per eseguire i comandi, indipendentemente da# quanto specificato all'interno di «/etc/passwd».SHELL=/bin/sh# Invia i messaggi di posta elettronica all'utente «fede»,# indipendentemente dal proprietario di questo file crontab.MAILTO=fede# Esegue 5 minuti dopo la mezzanotte di ogni giorno.5 0 * * * $HOME/bin/salvataggiodati# Esegue alle ore 14:15 del primo giorno di ogni mese.# L'output viene inviato tramite posta elettronica all'utente«tizio».15 14 1 * * $HOME/bin/mensile# Esegue alle 22 di ogni giorno lavorativo (da lunedì al venerdì).# In particolare viene inviato un messaggio di posta elettronica a«fede».0 22 * * 1-5 mail -s "Sono le 22" fede# Esegue 23 minuti dopo mezzanotte, dopo le due, dopo le quattro,...,# ogni giorno.23 0-23/2 * * * echo "Ciao ciao"# Esegue alle ore 04:05 di ogni domenica.5 4 * * 0 echo "Buona domenica"

    FabioDelVigna- [email protected]

  • Esempio /etc/crontab

    SHELL=/bin/bashPATH=/sbin:/bin:/usr/sbin:/usr/binMAILTO=root# Run any at jobs every minute* * * * * root [ -x /usr/sbin/atrun ] && /usr/sbin/atrun# run-parts è un programma che avvia tutti gli eseguibili contenuti nella directory indicata come argomento01 * * * * root run-parts /etc/cron.hourly02 1 * * * root run-parts /etc/cron.daily02 2 * * 0 root run-parts /etc/cron.weekly02 3 1 * * root run-parts /etc/cron.monthly

    # esegue uno script di backup ogni 10 minuti*/10 * * * * root /root/bin/backupscript

    FabioDelVigna- [email protected]

  • Note

    run-parts /etc/periodic/hourly

    § avviatuttoquellocheènelladirectory

    § Alcuneversionirichiedonounnewline primadiEOFpereseguirel’ultimocomando

    FabioDelVigna- [email protected]

    Per inserire un'elaborazione nei momenti più comuni, basta metterla nella directory che rappresenta la cadenza desiderata.

  • Esercizi

    FabioDelVigna- [email protected]

  • Esercizi (1 di 5)

    /*loop_inf.c*/#includeint main (void ){

    while (1){}return 1;

    }

    FabioDelVigna- [email protected]

  • Esercizi (2 di 5)

    /*loop_time.c*/#include#includeint main (void ){

    while (1){time(NULL);}return 1;

    }

    FabioDelVigna- [email protected]

  • Esercizi (3 di 5)

    /*loop_sleep.c*/#include#includeint main (void ){

    while (1){int i;sleep (4);for(i=0;i<1000000000;i++);

    }return 1;

    }

    FabioDelVigna- [email protected]

  • Esercizi (4 di 5)

    § Utilizzareilprogrammaloop_inf.c§ compilareilprogramma(cc -Wall -o )

    § eseguireilprogrammacomeutenteutentenuovo§ tramitetop (*lanciatodautenteroot*)controllarelostato

    dellaCPU§ giustificarel'outputditop§ modificareillivellodinice tramiteilcomandointerattivoditop

    § comecambial'outputditop rispettoaprima(relativamenteall'utilizzodellaCPU)?

    § terminareilprogrammausandoilcomandointerattivokilldadentrotop

    § Utilizzareilprogrammaloop_time.c§ compilareedeseguirecomeutentesisoper§ controllareledifferenzedell'outputditop (*lanciatoda

    utenteroot*)rispettoaprima§ terminareilprogramma

    FabioDelVigna- [email protected]

  • Esercizi (5 di 5)

    § Utilizzareilprogrammaloop_sleep.c§ compilareedeseguirecomeutentesisoper§ settarea1secondol'intervallodiupdateditop(*lanciatodautenteroot*)

    § visualizzaresoloiprocessicheappartengonoall'utenteconcuiilprogrammaèstatolanciato

    § ordinarel'outputsecondoilcampotime§ controllaretramitetop glistatiincuipassailprocessoedillivellodipriorità

    § terminareilprocesso§ Usareps perottenerel'elencotuttiiprocessiin

    esecuzionesullamacchina,§ modificandoleinformazioniinoutputtramiteleopzioni-o e-O

    FabioDelVigna- [email protected]