informatica:sol:laboratorio15:esercitazionia:scexamples
Questa è una vecchia versione del documento!
Indice
Alcuni esempi di semplici programmi C con processi e pipe
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.
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/wait.h> #include <errno.h> // utility macro #define SYSCALL(r,c,e) \ if((r=c)==-1) { perror(e);exit(errno); } // numero di processi di default const int NPROC = 2; // forward declaration, procedura eseguita da un processo void procF(int); int main(int argc, char * argv[]) { int nproc; // check arguments if(argc>1) nproc = atoi(argv[1]); else nproc = NPROC; // per distinguere tra il processo padre ed i processi figli int ppid = getpid(); // genero nproc processi figli for(int i=0;i<nproc;i++) { int r; SYSCALL(r,fork(),"creando un processo"); if(r == 0) { // processo figlio procF(i+2); // eseguo i+2 iterazioni break; // altrimenti genero troppi processi } else { // processo padre printf("Creato processo figlio con pid %d\n",r); // continua il ciclo } } // il solo processo padre attende i figlio if(getpid() == ppid) { int status,r; for(int i=0;i<nproc;i++) { SYSCALL(r, wait(&status), "wait"); if(WIFEXITED(status)) printf("Figlio con pid %d terminato con exit, codice %d\n", r, WEXITSTATUS(status)); else if (WIFSIGNALED(status)) { printf("Figlio con pid %d terminato da un segnale (sig=%d)\n", r, WTERMSIG(status)); } else if (WIFSTOPPED(status) || WIFCONTINUED(status)) printf("Figlio con pid %d interrotto da o ripartito con un segnale\n",r); } } // else sono un processo figlio e termino senza fare nient'altro return getpid() % 256; // termino con questo codice } // procedura eseguita dai processi figli void procF(int niter) { for(int i=0;i<niter;++i) { printf("Sono il processo %d all'iterazione %d\n",getpid(),i); sleep(1); } }
command.c
Programma che prende come argomento un programma eseguibile ed i suoi eventuali argomenti e lancia il programma attendendone la terminazione.
#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; }
pipe2proc.c
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:
echo "Ciao mondo ! Passo e chiudo ..." | tr ' ' '\n' | LC_ALL=C sort
#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; }
informatica/sol/laboratorio15/esercitazionia/scexamples.1430041631.txt.gz · Ultima modifica: 26/04/2015 alle 09:47 (10 anni fa) da Massimo Torquati