informatica:sol:laboratorio15:esercitazionia:scexamples

Differenze

Queste sono le differenze tra la revisione selezionata e la versione attuale della pagina.

Link a questa pagina di confronto

Entrambe le parti precedenti la revisioneRevisione precedente
Prossima revisione
Revisione precedente
informatica:sol:laboratorio15:esercitazionia:scexamples [26/04/2015 alle 09:23 (10 anni fa)] Massimo Torquatiinformatica:sol:laboratorio15:esercitazionia:scexamples [26/04/2015 alle 13:34 (10 anni fa)] (versione attuale) – [command.c (chiamate: fork, wait, getpid, execvp)] Massimo Torquati
Linea 1: Linea 1:
 ===== Alcuni esempi di semplici programmi C con processi e pipe ===== ===== Alcuni esempi di semplici programmi C con processi e pipe =====
  
-==== nproc.c ====+==== nproc.c (chiamate: fork, wait, getpid) ====
 Si creano ''nproc'' processi figli che eseguono un certo numero di iterazioni, si attende quindi la loro terminazione stampando la condizione di terminazione l'exit status e l'eventuale segnale che ha terminato il processo. Si creano ''nproc'' processi figli che eseguono un certo numero di iterazioni, si attende quindi la loro terminazione stampando la condizione di terminazione l'exit status e l'eventuale segnale che ha terminato il processo.
  
Linea 70: Linea 70:
     sleep(1);     sleep(1);
   }   }
 +}
 +</code>
 +
 +==== command.c (chiamate: fork, wait, getpid, execvp) ====
 +
 +Programma che prende come argomento un programma eseguibile ed i suoi eventuali argomenti e lancia il programma attendendone la terminazione. 
 +<code>
 +#include <stdlib.h>
 +#include <stdio.h>
 +#include <sys/wait.h>        
 +#include <sys/types.h>       
 +#include <unistd.h>          
 +#include <errno.h>           
 +
 +// utility macro
 +#define SYSCALL(r,c,e) \
 +    if((r=c)==-1) { perror(e);exit(errno); }
 +
 +int main(int argc, char *argv[]) {
 +    if (argc == 1) {
 + fprintf(stderr, "usa: %s comando [argomenti-comando]\n", argv[0]);
 + return EXIT_FAILURE;
 +    }
 +    
 +    int pid;
 +    SYSCALL(pid, fork(), "fork");
 +  
 +    if(pid == 0) { // figlio 
 + int r;
 + execvp(argv[1],&argv[1]);
 + perror("execvp");
 + return errno;
 +    } 
 +    int status;
 +    SYSCALL(pid, wait(&status),"wait");
 +    printf("Processo %d terminato con ",pid);
 +    if(WIFEXITED(status))  printf("exit(%d)\n",WEXITSTATUS(status));
 +    else printf("un segnale (sig=%d)\n", WTERMSIG(status));
 +    return 0;
 +}
 +</code>
 +
 +==== zombie.c (chiamate: fork, waitpid, getpid, execlp) ====
 +
 +Il seguente programma crea un numero di processi ''zombie'' mostrando il loro stato con il comando unix 'ps'.
 +
 +<code>
 +#include <stdio.h>
 +#include <unistd.h>
 +#include <stdlib.h>
 +#include <errno.h>
 +#include <sys/wait.h>
 +
 +// utility macro
 +#define SYSCALL(r,c,e) \
 +    if((r=c)==-1) { perror(e);exit(errno); }
 +
 +int main(int argc, char * argv[]) {
 +    const int SEC=2;
 +
 +    if (argc != 2) {
 + fprintf(stderr, "usa: %s num-proc\n", argv[0]);
 + return EXIT_FAILURE;
 +    }
 +    
 +    int nproc = atoi(argv[1]);
 +    int pid;    
 +    for(int i=0;i<nproc;++i) {
 + SYSCALL(pid,fork(),"fork");
 + if(pid==0) { // figlio 
 +     sleep(SEC);
 +     exit(0); // esco con successo
 + } else 
 +     printf("%d: creato processo con pid = %d\n",  getpid(), pid);    
 +    }
 +    
 +    // solo il processo padre arriva qui
 +
 +    // aspettiamo un po' in modo da essere "sicuri" 
 +    // che i processi figli siano terminati
 +    sleep(2*SEC); 
 +
 +    printf("Stato dei processi prima delle wait:\n");
 +    SYSCALL(pid,fork(),"fork");
 +    if(pid==0) {
 + execlp("ps","ps",NULL);
 + perror("eseguendo ps");
 + exit(errno);
 +    } else {
 + int stato;
 + printf("Lanciato il processo con pid = %d per eseguire un ps\n",pid);
 + SYSCALL(pid,waitpid(pid,&stato,0),"waitpid");
 + printf("Processo %d terminato\n",pid);
 +    }
 +
 +    // adesso attendiamo la terminazione dei processi
 +    for(int i=0;i<nproc;++i) {
 + int stato;
 + SYSCALL(pid,wait(&stato),"wait");
 + if(WIFEXITED(stato)) 
 +     printf("Processo con pid %d terminato con una exit(%d)\n",
 +    pid,WEXITSTATUS(stato));
 +    }
 +    printf("Stato dei processi dopo la terminazione:\n");
 +    SYSCALL(pid,fork(),"creando il processo ps");
 +    if(pid==0) {
 + execlp("ps","ps",NULL);
 + perror("eseguendo il ps");
 + exit(0);
 +    } else {
 + int stato;
 + SYSCALL(pid,waitpid(pid,&stato,0),
 + "attendendo la terminazione del processo ps");
 +    }
 +    return 0;
 +}
 +</code>
 + 
 +==== pipe2proc.c (chiamate: fork, wait, getpid, write, pipe, dup, execve) ====
 +
 +Il programma crea un processo figlio che esegue il comando ''sort'' sull'input ricevuto in una ''pipe'' che connette lo standard output del padre con lo standard input del figlio ( padre -- ''pipe'' --> figlio).\\
 +Il programma produce in output l'equivalente prodotto dal comando shell:
 +<code>
 +echo "Ciao mondo ! Passo e chiudo ..." | tr ' ' '\n' | LC_ALL=C sort 
 +</code>
 +
 +
 +<code>
 +#include <unistd.h>
 +#include <stdlib.h>
 +#include <stdio.h>
 +#include <sys/types.h>
 +#include <sys/wait.h>
 +#include <string.h>
 +#include <errno.h>
 +
 +// utility macro
 +#define SYSCALL(r,c,e) \
 +    if((r=c)==-1) { perror(e);exit(errno); }
 +
 +
 +int main(int argc, char *argv[]) {    
 +    int canale[2];
 +
 +    int r;
 +    SYSCALL(r, pipe(canale), "pipe");
 +
 +    if (fork() != 0) {  // padre
 + close(1);
 + SYSCALL(r,dup(canale[1]),"dup");
 +
 + // chiudo tutti i descrittori che non uso
 + close(canale[1]);
 + close(canale[0]);
 +    } else {            // figlio
 + close(0);
 + SYSCALL(r, dup(canale[0]), "dup");
 +
 + // chiudo tutti i descrittori che non uso prima di chiamare la exec
 + close(canale[1]);
 + close(canale[0]);
 +
 + // utilizzo la chiamata di sistema execve specificando le
 + // variabili di ambente del processo sort
 + char *path = getenv("PATH");
 + char envpath[strlen("PATH=")+strlen(path)+1];
 + char envlcall[] = "LC_ALL=C";
 + snprintf(envpath, sizeof(envpath), "PATH=%s",path); 
 + char *envp[] = { envpath, envlcall, NULL};
 + char *cmd[]  = { "/usr/bin/sort", NULL };
 +
 + execve(cmd[0], cmd, envp);
 + perror("execve");
 + exit(errno);
 +    }
 +
 +    SYSCALL(r, write(1, "mondo\n", 7), "write1");
 +    SYSCALL(r, write(1, "Ciao\n", 6), "write2");
 +    SYSCALL(r, write(1, "!\n", 3), "write3");
 +    SYSCALL(r, write(1, "Passo\n", 7), "write3");
 +    SYSCALL(r, write(1, "e\n", 3), "write3");
 +    SYSCALL(r, write(1, "chiudo\n", 8), "write3");
 +    SYSCALL(r, write(1, "...", 4), "write3");
 +     
 +    // chiudo l'output prima di attendere la terminazione
 +    close(1);
 +
 +    // attendo la terminazione del processo figlio
 +    int status;
 +    SYSCALL(r, wait(&status), "wait");
 +    return 0;
 } }
 </code> </code>
informatica/sol/laboratorio15/esercitazionia/scexamples.1430040212.txt.gz · Ultima modifica: 26/04/2015 alle 09:23 (10 anni fa) da Massimo Torquati

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki