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

Prossima revisione
Revisione precedente
informatica:sol:laboratorio15:esercitazionia:scexamples [26/04/2015 alle 09:21 (10 anni fa)] – creata 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 processi figli che eseguono un certo numero di iterazioni ognuno e si attende la terminazione di ogni processo.+Si creano ''nproc'' processi figli che eseguono un certo numero di iterazionisi attende quindi la loro terminazione stampando la condizione di terminazione l'exit status e l'eventuale segnale che ha terminato il processo.
  
 <code> <code>
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.1430040068.txt.gz · Ultima modifica: 26/04/2015 alle 09:21 (10 anni fa) da Massimo Torquati

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki