#define _POSIX_C_SOURCE 200112L #include #include #include #include #include #include #include #include "err.h" #define MAX 100 #define DEBUG 1 // 0: pas de messages. 1: affiche les identités des // processus et les connexions par les tubes. /*-----------------------------------------------------------------------------. | Crée un anneau de processus reliés par des tubes. Chaque processus exécute | | ensuite l'algorithme d'élection de Dolev-Klawe-Rodeh (1982). | | | | L'identité des processus utilisée par l'algorithme DKR est passée à execlp. | `-----------------------------------------------------------------------------*/ /*------------------------------------------------------------------. | Diffère de anneau_proc.c/DKR.c par l'attribution des identités: | | dans cette version, elles sont générées aléatoirement pour ne pas | | avoir des pid consécutifs. | `------------------------------------------------------------------*/ // Génère un tableau aléatoire de n entiers distincts 0, 1,..., n-1. int *generer_tableau_identites(int n) { int *t = (int *)calloc(n,sizeof(int)); int k; struct timeval time; gettimeofday(&time, NULL); srand(time.tv_sec); // srandom() meilleur sous OS X. for (int i = 0; i < n; ++i) { k = rand() % n; // Tirage d'une case pour placer i. while(t[(n+k)%n] != 0) // Case occupée. Recherche d'une place libre. k++; t[(n+k)%n] = i; } #if DEBUG printf("Tableau généré\n"); for (int i = 0; i < n; ++i) printf("%d ", t[i]); printf("\n"); #endif return t; } void anneau(int n) { int tubes[n][2]; int *ids = generer_tableau_identites(n); char identite[MAX]; for (int i = 0; i < n; ++i) if (pipe(tubes[i]) < 0) FATAL("pipe"); for (int i = 0; i < n; ++i) { switch(fork()) { case -1: FATAL("fork"); case 0: dup2(tubes[(i-1+n)%n][0], STDIN_FILENO); dup2(tubes[i][1], STDOUT_FILENO); #if DEBUG fprintf(stderr, "Tube%d => Proc[i=%d, pid=%d, moi=%d] => Tube%d\n", (i-1+n)%n, i, getpid(), ids[i], i); #endif for (int j=0; j < n; j++) { close(tubes[j][0]); close(tubes[j][1]); } snprintf(identite, MAX, "%d", ids[i]); execlp("./DKR_rand", "DKR_rand", identite, NULL); FATAL("execlp"); default: continue; } } } int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "Usage: %s \n", argv[0]); return EXIT_FAILURE; } anneau(atoi(argv[1])); while(wait(NULL)) ; return EXIT_SUCCESS; }