# Sémaphore et processus

**URL:** <https://www.debian-fr.org/t/semaphore-et-processus/24320>\
**Category:** Programmation\
**Created:** [Février 20, 2016, 9:21 UTC](https://www.debian-fr.org/t/semaphore-et-processus/24320 "2016-02-20T21:21:01Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![dagost](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/d/a5b964/32.png) [@dagost](https://www.debian-fr.org/u/dagost)\
**Post date:** [Février 20, 2016, 9:21 UTC](https://www.debian-fr.org/t/semaphore-et-processus/24320/1 "2016-02-20T21:21:01Z")

</div>

Bonjour,

Actuellement je tente de comprendre les IPC de type sémaphore en codant un programme qui crée 20 processus, chaque processus correspond à une personne qui veut rentrer dans un ascenseur de manière synchronisé de façon à ce qu’il n’y ait qu’une personne dans l’ascenseur à la fois. Dès qu’un processus est rentré dans l’ascenseur (la zone critique du sem) il se termine.

[code]#include \<stdio.h\>  
#include \<stdlib.h\>  
#include \<sys/types.h\>  
#include \<sys/ipc.h\>  
#include \<sys/sem.h\>

int main(int argc, char \* argv[]) {

```
int i;
int N = 20;
pid_t tab[N];

key_t cle;
int semid;
int val[1]={1};

struct sembuf p, v;

cle = ftok(argv[0],0);
semid = semget(cle,1,IPC_CREAT|0666);

semctl(semid,0,SETVAL,val);

p.sem_num = 0;
p.sem_op = -1;
p.sem_flg = 0;

v.sem_num = 0;
v.sem_op = 1;
v.sem_flg = 0;

for(i=0; i<N; i++) {

	tab[i] = fork();

	if(tab[i] == 0) {
		semop(semid, &p, 1);
		printf("Je suis le fils %d et je rentre dans l'ascenseur",getpid());
		semop(semid, &v, 1);
		return EXIT_SUCCESS;
	} else {
		sleep(2);
		semctl(semid, 0, IPC_RMID, 0);
		return EXIT_SUCCESS;
	}
}

```

}[/code]

Je suis sous Debian amd64 et ce programme n’affiche rien. Est ce que quelqu’un pourrait m’éclairer ?

Merci d’avance !

---

<div class="post-metadata">

**Author:** ![fran.b](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/f/d78d45/32.png) [@fran.b](https://www.debian-fr.org/u/fran.b)\
**Post date:** [Février 20, 2016, 9:21 UTC](https://www.debian-fr.org/t/semaphore-et-processus/24320/2 "2016-02-20T21:21:02Z")

</div>

Ben si il affiche

`francois@totoche:/tmp$ ./sem 
francois@totoche:/tmp$ Je suis le fils 9344 et je rentre dans l'ascenseur
francois@totoche:/tmp$ 
`Une remarque ta boucle n’est effectuée qu’une fois ((x2 pour le fork()) à cause du return.

[code]#include \<stdio.h\>  
#include \<stdlib.h\>  
#include \<sys/types.h\>  
#include \<sys/ipc.h\>  
#include \<sys/sem.h\>

int main(int argc, char \* argv[]) {

int i;  
int N = 20;  
pid\_t tab[N];

key\_t cle;  
int semid;  
int val[1]={1};

struct sembuf p, v;

cle = ftok(argv[0],0);  
semid = semget(cle,1,IPC\_CREAT|0666);

semctl(semid,0,SETVAL,val);

p.sem\_num = 0;  
p.sem\_op = -1;  
p.sem\_flg = 0;

v.sem\_num = 0;  
v.sem\_op = 1;  
v.sem\_flg = 0;

for(i=0; i\<N; i++) {

```
  tab[i] = fork();

  if(tab[i] == 0) {
     semop(semid, &p, 1);
     printf("Je suis le fils %d et je rentre dans l'ascenseur\n",getpid());
     semop(semid, &v, 1);
  } else {
printf("Hou hou %d\n",getpid());
     sleep(2);
     semctl(semid, 0, IPC_RMID, 0);
  }

```

}  
return EXIT\_SUCCESS;

}  
[/code]correspond peut être à ce que tu veux faire…

---

<div class="post-metadata">

**Author:** ![fran.b](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/f/d78d45/32.png) [@fran.b](https://www.debian-fr.org/u/fran.b)\
**Post date:** [Février 20, 2016, 9:21 UTC](https://www.debian-fr.org/t/semaphore-et-processus/24320/3 "2016-02-20T21:21:03Z")

</div>

[code]#include \<stdio.h\>  
#include \<stdlib.h\>  
#include \<sys/types.h\>  
#include \<sys/ipc.h\>  
#include \<sys/sem.h\>

int main(int argc, char \* argv[]) {

int i,pr;  
int N = 3;  
pid\_t tab[N];

key\_t cle;  
int semid;  
int val[1]={1};

struct sembuf p, v;

cle = ftok(argv[0],0);  
semid = semget(cle,1,IPC\_CREAT|0666);

semctl(semid,0,SETVAL,val);

p.sem\_num = 0;  
p.sem\_op = -1;  
p.sem\_flg = 0;

v.sem\_num = 0;  
v.sem\_op = 1;  
v.sem\_flg = 0;

for(i=0; i\<N; i++) {  
pr = getpid();  
tab[i] = fork();

```
  if(tab[i] == 0) {
     semop(semid, &p, 1);
     printf("Je suis le fils %d de %d %d et je rentre dans l'ascenseur\n",i,pr,getpid());
     semop(semid, &v, 1);
  } else {
     sleep(2);
     semctl(semid, 0, IPC_RMID, 0);
  }

```

}  
return EXIT\_SUCCESS;

}  
[/code]t’aidera à comprendre pourquoi tu as plein de lignes affichées. (Exercice: combien de lignes 🙂)

---

<div class="post-metadata">

**Author:** ![BBT1](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/b/ecc23a/32.png) [@BBT1](https://www.debian-fr.org/u/BBT1)\
**Post date:** [Février 20, 2016, 9:21 UTC](https://www.debian-fr.org/t/semaphore-et-processus/24320/4 "2016-02-20T21:21:03Z")

</div>

> [@](#):
>
> cle = ftok(argv[0],0);

Le deuxième argument de ftok (int proj\_id) doit être non nul (cf. man ftok(3))  
Il faut aussi tester le code de retour pour voir si il y a eu une erreur (cle == -1)

---

<div class="post-metadata">

**Author:** ![fran.b](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/f/d78d45/32.png) [@fran.b](https://www.debian-fr.org/u/fran.b)\
**Post date:** [Février 20, 2016, 9:21 UTC](https://www.debian-fr.org/t/semaphore-et-processus/24320/5 "2016-02-20T21:21:03Z")

</div>

> [@](#):
>
> [quote]cle = ftok(argv[0],0);

Le deuxième argument de ftok (int proj\_id) doit être non nul (cf. man ftok(3))  
Il faut aussi tester le code de retour pour voir si il y a eu une erreur (cle == -1)[/quote]  
Tu es sûr de toi pour le id non nul?? Je ne trouve nulle part ça. [http://www.linux-kheops.com/doc/man/manfr/man-html-0.9/man3/ftok.3.html](http://www.linux-kheops.com/doc/man/manfr/man-html-0.9/man3/ftok.3.html) par exemple…

---

<div class="post-metadata">

**Author:** ![BBT1](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/b/ecc23a/32.png) [@BBT1](https://www.debian-fr.org/u/BBT1)\
**Post date:** [Février 20, 2016, 9:21 UTC](https://www.debian-fr.org/t/semaphore-et-processus/24320/6 "2016-02-20T21:21:03Z")

</div>

> [@](#):
>
> `semid = semget(cle,1,IPC_CREAT|0666);`

Il faut aussi tester le retour de semget (je sais, les codes tester les codes de retour partour c’est chiant, mais on est content d’avoir codé proprement quand ça marche pas et qu’il faut trouver l’erreur)  
Et personnelement, j’aurais restreint les droits au maximum (je pense que c’est une bonne habitude)

---

<div class="post-metadata">

**Author:** ![dagost](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/d/a5b964/32.png) [@dagost](https://www.debian-fr.org/u/dagost)\
**Post date:** [Février 20, 2016, 9:21 UTC](https://www.debian-fr.org/t/semaphore-et-processus/24320/7 "2016-02-20T21:21:03Z")

</div>

Merci de vos réponses !

Je ne savais pas pour le second argument du ftok, là en l’occurrence ce n’est pas cela qui pose problème. L’IPC est bien crée (vérifié avec la commande ipcs) - je ne mets pas le de vérification pour ne pas alourdir mon code sur le forum.

En fait, je ne comprends pas pourquoi je ne peux pas mettre de return (quid du exit ?) dans la condition if. Dans un if classique je comprends pourquoi mais dans ce cas là il s’agit d’une condition if de gestion de processus et donc le return devrait être exécuté à la fin de chaque processus fils non ? Parce que là du coup je ne sais pas comment terminer chaque processus fils dès qu’il a eu le sémaphore …

---

<div class="post-metadata">

**Author:** ![BBT1](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/b/ecc23a/32.png) [@BBT1](https://www.debian-fr.org/u/BBT1)\
**Post date:** [Février 20, 2016, 9:21 UTC](https://www.debian-fr.org/t/semaphore-et-processus/24320/8 "2016-02-20T21:21:03Z")

</div>

Hum j’ai la page de man sous les yeux :

```auto
DESCRIPTION
       La fonction ftok() utilise l'identité du fichier indiqué par pathname (qui doit exister et être accessible), et les huit bits de poids faible de
       proj_id (qui doit être non nul) pour créer une clé IPC System V de type key_t, utilisable avec msgget(2), semget(2) ou shmget(2).
```

Pareil pour la version anglaise.

---

<div class="post-metadata">

**Author:** ![BBT1](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/b/ecc23a/32.png) [@BBT1](https://www.debian-fr.org/u/BBT1)\
**Post date:** [Février 20, 2016, 9:21 UTC](https://www.debian-fr.org/t/semaphore-et-processus/24320/9 "2016-02-20T21:21:04Z")

</div>

[quote=“dagost”]Merci de vos réponses !

Je ne savais pas pour le second argument du ftok, là en l’occurrence ce n’est pas cela qui pose problème. L’IPC est bien crée (vérifié avec la commande ipcs) - je ne mets pas le de vérification pour ne pas alourdir mon code sur le forum.

En fait, je ne comprends pas pourquoi je ne peux pas mettre de return (quid du exit ?) dans la condition if. Dans un if classique je comprends pourquoi mais dans ce cas là il s’agit d’une condition if de gestion de processus et donc le return devrait être exécuté à la fin de chaque processus fils non ? Parce que là du coup je ne sais pas comment terminer chaque processus fils dès qu’il a eu le sémaphore …[/quote]

Tu peux mettre un return au fils,  
mais pas au père il doit finir sa boucle.

---

<div class="post-metadata">

**Author:** ![dagost](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/d/a5b964/32.png) [@dagost](https://www.debian-fr.org/u/dagost)\
**Post date:** [Février 20, 2016, 9:21 UTC](https://www.debian-fr.org/t/semaphore-et-processus/24320/10 "2016-02-20T21:21:04Z")

</div>

Effectivement je comprends bien mon erreur maintenant :smt003

Pour les droits je vais passer à 0600 tant qu’à faire.

Merci beaucoup

---

<div class="post-metadata">

**Author:** ![BBT1](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/b/ecc23a/32.png) [@BBT1](https://www.debian-fr.org/u/BBT1)\
**Post date:** [Février 20, 2016, 9:21 UTC](https://www.debian-fr.org/t/semaphore-et-processus/24320/11 "2016-02-20T21:21:04Z")

</div>

`int val[1]={1};
semctl(semid,0,SETVAL,val);`

Là aussi ça va pas, mais plus pour un point de vue esthétique,  
pour faire les choses propres je te proposes

```auto

```

ou alors pour pousser le bouchon

`#ifdef _SEM_SEMUN_UNDEFINED
union semun {
     int val; // <= value for SETVAL
     struct semid_ds *buf; // <= buffer for IPC_STAT & IPC_SET
     unsigned short int *array; // <= array for GETALL & SETALL
     struct seminfo *__buf; // <= buffer for IPC_INFO
} val = {.val = 1};
#endif`

Mais bon tout ça c’est juste pour dire que je comprenais pas pourquoi tu avais un tableau à une case 😉

---

<div class="post-metadata">

**Author:** ![dagost](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/d/a5b964/32.png) [@dagost](https://www.debian-fr.org/u/dagost)\
**Post date:** [Février 20, 2016, 9:21 UTC](https://www.debian-fr.org/t/semaphore-et-processus/24320/12 "2016-02-20T21:21:04Z")

</div>

On m’a apprit comme ça (très mal) donc je continue à le faire ☹

---

<div class="post-metadata">

**Author:** ![BBT1](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/b/ecc23a/32.png) [@BBT1](https://www.debian-fr.org/u/BBT1)\
**Post date:** [Février 20, 2016, 9:21 UTC](https://www.debian-fr.org/t/semaphore-et-processus/24320/13 "2016-02-20T21:21:04Z")

</div>

Heu ya des problèmes de fond aussi…  
on ne voit rien si le père lance un fils toutes les 2 secondes,  
et que le fils se termine quasiment instantanément.

Il faut que se soit le fils qui prenne du temps,  
et le père doit attendre que ses fils soient terminés avant de détruire le sémaphore.

---

<div class="post-metadata">

**Author:** ![BBT1](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/b/ecc23a/32.png) [@BBT1](https://www.debian-fr.org/u/BBT1)\
**Post date:** [Février 20, 2016, 9:21 UTC](https://www.debian-fr.org/t/semaphore-et-processus/24320/14 "2016-02-20T21:21:04Z")

</div>

Et pour le pointeur pour val,  
je suis pas du tout d’accord,  
le man dit :

`int semctl(int semid, int semnum, int cmd, ...);
La fonction a trois ou quatre arguments, selon la valeur de cmd. Quand il y en a quatre, le quatrième est de type union semun.
union semun {
  int val; /* Valeur pour SETVAL */
  struct semid_ds *buf; /* Tampon pour IPC_STAT, IPC_SET */
  unsigned short *array; /* Tableau pour GETALL, SETALL */
  struct seminfo *__buf; /* Tampon pour IPC_INFO (spécifique à Linux) */
};`  
Donc pointeur pour buf, array et \_\_buf, mais pas pour val.  
De toute manière, ça te sautera aux yeux quand ton programme de test marchera,  
tu auras une valeur de val abhérente puisqu’il utilisera l’adresse plutot que la valeur de ton int.

---

<div class="post-metadata">

**Author:** ![dagost](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/d/a5b964/32.png) [@dagost](https://www.debian-fr.org/u/dagost)\
**Post date:** [Février 20, 2016, 9:21 UTC](https://www.debian-fr.org/t/semaphore-et-processus/24320/15 "2016-02-20T21:21:05Z")

</div>

Oui oui j’ai édité, j’ai pris un seg fault en fait.

---

<div class="post-metadata">

**Author:** ![BBT1](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/b/ecc23a/32.png) [@BBT1](https://www.debian-fr.org/u/BBT1)\
**Post date:** [Février 20, 2016, 9:21 UTC](https://www.debian-fr.org/t/semaphore-et-processus/24320/16 "2016-02-20T21:21:08Z")

</div>

Par contre pour le ftok, j’ai fouillé un peu  
et impossible de trouver une explication pour l’argument non nul.

Par contre, je tiens à préciser que la manière dont ftok est implémenté  
ne garantit absolument pas d’avoir une clé unique,  
la fonction se contente de prendre quelques bit de l’inode, du périphérique du fichier  
et 1 octet sur l’entier passé et de renvoyer ça avec des décalages de bit…

Si quelqu’un a l’explication, je suis preneur 😉
