Traitement parallèle et synchronisation à l’aide de sémaphores en C

Des questions:

  1. Mes processus fonctionnent-ils en parallèle? Je veux six processus en parallèle.
  2. Comment synchroniser ces processus (parent avec cinq processus enfants) en utilisant des sémaphores, dans une boucle infinie? Donc, la sortie serait: 1 2 3 4 5 réinitialiser 1 2 3 4 5 réinitialiser etc …
  3. Une documentation simple et compréhensible sur les sémaphores?

Code:

#include  #include  #include  #include  parentWithFiveChildren() { printf("1 "); //Parent fflush(stdout); int i, status; for (i = 2; i  0) printf("\a"); return 0; } int main(void) { parentWithFiveChildren(); } 

Sortie:

 1 2 3 4 5 reset 

1. Parallélisme

Non, les processus ne s’exécutent pas en parallèle (ou, au moins, ils ne sont exécutés que de manière transitoire en parallèle, et seulement deux processus à la fois), mais uniquement parce que:

  1. Le sleep(1) donne au processus parent un long moment (au moins une seconde) ne faisant rien.
  2. L’enfant finit et sort pendant cette seconde.

Votre code d’impression dans l’enfant est impair; il n’y a effectivement aucune différence entre le i == 6 et les autres opérations. Dans main() , return 0; et exit(0); sont pratiquement les mêmes – il peut y avoir des différences, mais elles sont obscures et ne correspondent pas à votre code.

Vous devriez #include et vous devriez collecter le PID (et le statut) des enfants morts; cela rendrait les choses plus claires pour vous.

Vous pouvez également demander aux enfants de dormir pendant un moment (par exemple 7 secondes chacun). Cela vous donnerait tous les processus enfants en cours d’exécution (en fait, en train de dormir) en parallèle, et le parent attend alors que les enfants quittent:

 #include  #include  #include  #include  int main(void) { printf("[PARENT] with pid %d\n", getpid()); fflush(stdout); for (int i = 2; i < 7; i++) // Odd loop conditions, but not wrong { sleep(1); if (fork() == 0) { printf("[CHILD] with pid %d from parent with pid %d\n", getpid(), getppid()); fflush(stdout); sleep(7); printf("[CHILD] with pid %d exiting with status %d\n", getpid(), i); exit(i); } } int corpse; int status; while ((corpse = wait(&status)) > 0) printf("%d: child %d exited with status 0x%.4X\n", getpid(), corpse, status); return 0; } 

Sortie de l’échantillon:

 $ ./test-forking [PARENT] with pid 13904 [CHILD] with pid 13905 from parent with pid 13904 [CHILD] with pid 13906 from parent with pid 13904 [CHILD] with pid 13907 from parent with pid 13904 [CHILD] with pid 13908 from parent with pid 13904 [CHILD] with pid 13909 from parent with pid 13904 [CHILD] with pid 13905 exiting with status 2 13904: child 13905 exited with status 0x0200 [CHILD] with pid 13906 exiting with status 3 13904: child 13906 exited with status 0x0300 [CHILD] with pid 13907 exiting with status 4 13904: child 13907 exited with status 0x0400 [CHILD] with pid 13908 exiting with status 5 13904: child 13908 exited with status 0x0500 [CHILD] with pid 13909 exiting with status 6 13904: child 13909 exited with status 0x0600 $ 

Une mise à niveau du code imprime également l’heure avec chaque ligne de sortie.

2. tuer

N’importe lequel des processus (dans l’ensemble créé par le parent) peut tuer tout autre processus (dans l’ensemble) qu’il connaît, en utilisant l’appel système kill() . Il n’est pas clair si vous voulez que le premier enfant ou le dernier enfant tue le parent, ou autre chose. Si le premier enfant tue le parent, le premier enfant sera le seul enfant (à cause des retards). Il n’est pas clair non plus pourquoi vous voulez envoyer des signaux entre les processus.

3. en boucle

Oui, vous pouvez faire quelque chose – la question est de savoir ce que vous êtes vraiment après. L’impression simple du parent et de l’ child plusieurs fois ne nécessite pas plusieurs processus. Si vous voulez que le parent dise “Je suis ici”, et que chaque enfant dise “Je suis ici” périodiquement, vous devez faire en sorte que les enfants se mettent en boucle et qu’ils dorment, et que tous les enfants aient été créés. . Pas difficile à faire

question 3). … Puis-je mettre la fonction principale dans une boucle infinie … ?

Bien sûr, vous pouvez :

 int main(void) { int c=0; while((c != 'q') && (c != EOF))//loops until c == q (and c!=EOF) { c = getchar();//waits until stdin sees a "q", (ie from keyboard) //An EOF (-1) or `q` will exit the loop //any other input will allow execution flow to continue, 1 loop at a time. //Add additional forking code here. //for each loop, spawn a new thread. //All secondary threads spawned will run parallel to other threads. } //exiting here will kill all threads (secondary and primary.) return 0; } 

1) Oui, votre processus parent et votre enfant s’exécutent en parallèle après fork. Vous pouvez le voir en boucle grâce à un processus enfant infini et en imprimant son nom pendant que les processus parent et autres font la même chose.

2) Oui, voici comment:

 #include  #include  #include  #include  #include  #include  int main() { pid_t pid; int i = 0; if ((pid = fork()) == 0) { if ((pid = getppid()) == -1) { fprintf(stderr, "child error: getppid()\n"); exit(1); } if (kill(pid, 9) == -1) { fprintf(stderr, "child error: kill()\n"); exit(1); } while (true) { printf ("child %d\n", ++i); } } else if (pid == -1) { fprintf(stderr, "error: fork()\n"); return 1; } while (true) { printf("parent %d\n", ++i); } return 0; } 

3) Si vous avez besoin de ce modèle spécifique, vous avez besoin d’une communication et d’une synchronisation interprocessus. Suggérez ceci