===== Alcuni esempi di semplici programmi C con processi e pipe senza nome ===== ==== nproc.c (chiamate usate: ''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 #include #include #include #include // 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 ==== command.c (chiamate usate: ''fork'', ''wait'', ''getpid'', ''execvp'') ==== Programma che prende come argomento un programma eseguibile ed i suoi eventuali argomenti e lancia il programma attendendone la terminazione. #include #include #include #include #include #include // 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; } ==== zombie.c (chiamate usate: ''fork'', ''waitpid'', ''getpid'', ''execlp'') ==== Il seguente programma crea un numero di processi ''zombie'' mostrando il loro stato con il comando unix ''ps''. #include #include #include #include #include // 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 ==== pipe2proc.c (chiamate usate: ''fork'', ''wait'', ''getpid'', ''write'', ''pipe'', ''dup'', ''execve'') ==== Il programma crea un processo figlio che esegue il comando ''sort'' sull'input ricevuto in una ''pipe'' senza nome 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 #include #include #include #include #include #include // 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; }