Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 29/03/2013, à 14:50

mortaurat

Sémaphore en C

Bonjour,
je dois mettre en œuvre dans le cadre d'un cours des "sémaphore" en C. Etant dans l'électronique (mais plutot à l'aise en C), je ne suis absolument pas famillié des sémaphores et autres processus.
Voici le code que j'ai écris pour l'instant :

#include <sys/types.h>     /* key_t  */
#include <sys/ipc.h>       /* ftok   */
#include <sys/sem.h>       /* semget, semctl, semop */
#include <sys/stat.h>      /* stat, struct stat  */
#include <stdlib.h>        /* malloc */
#include <stdio.h>         /* perror, printf */
#include <errno.h>         /* errno */

void lecteur() ;
void redacteur();
void redacteur();
void P(int *sem);
void V(int *sem);


void main()
{
   
}

void P(int *sem)
{
while(*sem<=0);
(*sem)--;
}

void V(int *sem)
{
(*sem)++;
}

void lecteur()
{
P(mutex);
if(nb_lecteur ==0) P(donnee);
nb_lecteur++;
V(mutex);
lire(donnee);
if(nb_lecteur == 1) V(donnee);
nb_lecteur -- ;
V(mutex);
}

void redacteur()
{
P(donnee);
ecrire(donnee);
V(donne);
}

Redacteur et lecteur doivent être des processus.
La variable nb_lecteur doit être stockée dans un segment de mémoire partagée (fuck me right).
Et je dois pouvoir vérifier le fonctionnement du tout.

Bref ça me dépasse complétement, savez vous comment je peux m'y prendre ?

Merci

Hors ligne

#2 Le 29/03/2013, à 15:37

telliam

Re : Sémaphore en C

tu ne dois pas recoder le P et le V.
utilises plutot : http://www.linux-kheops.com/doc/man/man … mop.2.html


"- Un intellectuel assis va moins loin qu'un con qui marche."
Maurice Biraud - Un Taxi pour Tobrouk
Michel Audiard

Hors ligne

#3 Le 29/03/2013, à 16:08

mortaurat

Re : Sémaphore en C

Je dois mettre quoi comme argument dans semop à pars le semid que j'obtient avec un semget() ?
Comment je crée mes processus ?
:'(

Hors ligne

#4 Le 29/03/2013, à 16:45

mfc_alpha

Re : Sémaphore en C

Bonjour,

L’écriture d'un sémaphore n'est pas si simple.
Juste un exemple pour ta fonction p et en supposant que tu as 2 thread.

Le premier thread fait:
p(sem1)

Le 2nd:
p(sem1)

Au début *sem1= 1
Le comportement suivant pourrait arriver :

Th1 test *sem1 -> il est toujours égale à 1 -> il sort de la boucle while
Ton programme est reschedulé, pas de bol mais c'est la vie, le th2 est exécuté:
Th2 test *sem1 -> il est toujours égale à 1 -> il sort de la boucle while

Tes 2 thread ont pris un sémaphore en même temps  -> c'est un échec.

Pour réaliser un sémaphore il faut utiliser des instructions atomic (qui ne peuvent etre interrompue). Celle ci dépendent de ton CPU.

Je te conseil donc d'utiliser une lib systeme qui fait déjà le travail.
En général on utilise la lib pthread sous linux et ses fonctions
pthread_mutex_lock(), pthread_mutex_unlock()

La lib pthread permet également de créer des threads:
pthread_create()

Je te conseil un google ou un man sur ces fonctions pour en apprendre plus.


Mathieu

Hors ligne

#5 Le 30/03/2013, à 00:16

telliam

Re : Sémaphore en C

non pas pthread, dans le cas il s'agit de semaphore inter-process pas inter-thread.


"- Un intellectuel assis va moins loin qu'un con qui marche."
Maurice Biraud - Un Taxi pour Tobrouk
Michel Audiard

Hors ligne

#6 Le 30/03/2013, à 09:45

telliam

Re : Sémaphore en C

tes processes peuvent etre 2 programmes différents ou alors tu forkes ton process.
pour semops : http://www.lifl.fr/~sedoglav/OS/main019.html#toc20


"- Un intellectuel assis va moins loin qu'un con qui marche."
Maurice Biraud - Un Taxi pour Tobrouk
Michel Audiard

Hors ligne

#7 Le 30/03/2013, à 18:36

mortaurat

Re : Sémaphore en C

Merci pour ton lien. Y'a vraiment plein de choses.
J'ai piqué la librairie qui était incluse, ça va faciliter l'utilisation des sémaphores.

Donc pour mon problème, j'ai du mal à voir comment articuler les choses.
J'ai commencé à créer une variable globale représentant le nombre de lecteur.
Ensuite j'ai écris dans mon main ()

void main()
{

 key_t key ;
 key = ftok(pathKey,PRJVAL);
 semid = sem_create(key, 0); //crée sémaphore avec Vinit = 0
	
}

ensuite je ne vois pas vraiment quoi mettre pour ce problème de "lecteurs/ecrivains"...
Aussi Redacteur et Lecteur doivent être des processus, je dois donc les déclarer comme processus ou comme une fonction normale ?
dans mon cours il y'a une ligne

Processus REDACTEUR
Processus LECTEUR

mais je ne sais pas si ça prend en C, vu que c'est du pseudo code...

Dernière modification par mortaurat (Le 30/03/2013, à 18:39)

Hors ligne

#8 Le 31/03/2013, à 11:38

telliam

Re : Sémaphore en C

Regarde la fonction fork(); ça devrait t'aider


"- Un intellectuel assis va moins loin qu'un con qui marche."
Maurice Biraud - Un Taxi pour Tobrouk
Michel Audiard

Hors ligne

#9 Le 31/03/2013, à 15:29

mortaurat

Re : Sémaphore en C

Bonjour,
alors j'ai utilisé la fonction fork() pour crée un processus fils qui executera une lecture, tandis que le pére se chargera de l'ecriture.

void main()
{
 /*
 La solution suivante permet de résoudre le problème des lecteurs et des rédacteurs en donnant priorité aux lecteurs. Cette solution nécessite trois sémaphores et une variable, à savoir :

    Un sémaphore M_Lect, initialisé à 1 qui permet de protéger la variable Lect. Il s'agit donc d'un mutex.
    Un sémaphore M_Red, initialisé à 1 qui permet de bloquer les tâches de rédaction (en induisant une priorité aux lecteurs). Il s'agit donc d'un mutex.
    Un sémaphore Red, initialisé à 1 qui permet de bloquer les tâches de lecture si une rédaction est en cours.
    Une variable Lect qui compte le nombre de lecteurs.
 */
 pid_t pid ;
 key_t key ;
 key = ftok("./data_file.txt",PRJVAL);
 red = sem_create (key, 1); //crée sémaphore avec Vinit = 1 
 M_red = sem_create (key, 1); //crée sémaphore avec Vinit = 1 
 M_lect = sem_create (key, 1); //crée sémaphore avec Vinit = 1 
 //mon code ici
 pid = fork();//va créer un processus fils.
 if(pid == 0)
 {
  quisuisje = "fils";//arbitrairement le fils sera le lecteur
  printf("je suis le %s, et je lance la lecture\n ",quisuisje); 
  lecteur();
  
 }
 else
 {
  quisuisje = "pére";//arbitrairement le fils sera le redacteur
  printf("je suis le %s, et je lance l'ecriture \n ",quisuisje); 
  redacteur();
 }

 //sem_delete(M_red);
 //sem_delete(M_lect);
 //sem_delete(red);
	
}

Je pense que j'ai un problème dans la creation de mes sémaphores, puisque leur id est à chaque fois 0.
Lors de l'exécution de mon programme j'ai une erreur de segmentation (core dumped).
Cette erreur arrive juste aprés l'execution de la fonction "P(M_red);" qui est dans la fonction redacteur.

Dernière modification par mortaurat (Le 31/03/2013, à 15:30)

Hors ligne

#10 Le 02/04/2013, à 20:27

mortaurat

Re : Sémaphore en C

Bon, j'ai reussi à faire mon code avec des thread, mais je me suis fait envoyer sur les roses par mon prof car je dois utiliser des processus.

#include <sys/types.h>     /* key_t  */
#include <sys/ipc.h>       /* ftok   */
#include <sys/sem.h>       /* semget, semctl, semop */
#include <sys/stat.h>      /* stat, struct stat  */
#include <stdlib.h>        /* malloc */
#include <stdio.h>         /* perror, printf */
#include <errno.h>         /* errno */

#define PRJVAL  1
#define ID_PROJET 'P'

void lecture();
void ecriture();

void V(int semid);
void P(int semid);
void sem_delete(int semid);

int nb_lecteur = 0;
int nbSem = 1 ;
const char* quisuisje = NULL ;
char data_fils[30];
int semid;
key_t clef;


void main(int argc, char *argv[])
{		
        pid_t pid;
	clef = ftok(argv[0], ID_PROJET);
	semid = semget(clef,1,IPC_CREAT | IPC_EXCL | 0666);//crée le sémaphore
	semctl(semid,0, SETVAL,1);//initialise le sémaphore à 1

	pid = fork();//va créer un processus fils.
	if(pid == 0)
	{
		P(semid);
		quisuisje = "fils";//arbitrairement le fils sera le lecteur
		printf("je suis le %s, et je lance la lecture\n",quisuisje); 
		lecture();
		printf("le pére a ecrit : %s \n", data_fils);
		V(semid);
	}
	else
	{
		P(semid);
		quisuisje = "pére";//arbitrairement le fils sera le redacteur
		printf("je suis le %s, et je lance l'ecriture \n ",quisuisje); 
		ecriture();
		V(semid);
	}

	//sem_delete(semid);
	//return 0;
}
/*
void lecture()
{
	printf("le pére a dit %s", data_fils);	
}

void ecriture()
{
	printf("Entrez votre mot : ");
	scanf("%s", data_fils);
 	printf("\n");
}*/

void lecture()
{
	FILE *f = fopen("./data_file.txt", "r");//ouverture du fichier en lecture
	fgets(data_fils,30,f);
	printf("le pére a dit %s, data_fils");
	fclose(f);
}

void ecriture()
{
	FILE *f = fopen("./data_file.txt", "w"); //ouverture fichier en ecriture
	fprintf(f, "luke, je suis ton pére ");
	fclose(f);
}


void P(int semid) {

  struct sembuf sempar ;

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

  if ( semop(semid,&sempar,1) == -1)
       perror("Erreur lors du down") ;
}


void V(int semid) {

  struct sembuf sempar ;

  sempar.sem_num = 0 ;
  sempar.sem_op = +1 ;
  sempar.sem_flg = 0 ;
  
  if (semop(semid,&sempar,1) ==-1)
    perror("Erreur lors du up") ;
}

void sem_delete(int semid){

  printf("destruction du s\\'emaphore %d\n",semid) ;

  if(semctl(semid,0,IPC_RMID,0) == -1)
    perror("Erreur lors de la destruction du semaphore") ;
}
#include <sys/types.h>     /* key_t  */
#include <sys/ipc.h>       /* ftok   */
#include <sys/sem.h>       /* semget, semctl, semop */
#include <sys/stat.h>      /* stat, struct stat  */
#include <stdlib.h>        /* malloc */
#include <stdio.h>         /* perror, printf */
#include <errno.h>         /* errno */

#define PRJVAL  1
#define ID_PROJET 'P'

void lecture();
void ecriture();

void V(int semid);
void P(int semid);
void sem_delete(int semid);

int nb_lecteur = 0;
int nbSem = 1 ;
const char* quisuisje = NULL ;
char data_fils[30];
int semid;
key_t clef;


void main(int argc, char *argv[])
{		
        pid_t pid;
	clef = ftok(argv[0], ID_PROJET);
	semid = semget(clef,1,IPC_CREAT | IPC_EXCL | 0666);//crée le sémaphore
	semctl(semid,0, SETVAL,1);//initialise le sémaphore à 1

	pid = fork();//va créer un processus fils.
	if(pid == 0)
	{
		P(semid);
		quisuisje = "fils";//arbitrairement le fils sera le lecteur
		printf("je suis le %s, et je lance la lecture\n",quisuisje); 
		lecture();
		printf("le pére a ecrit : %s \n", data_fils);
		V(semid);
	}
	else
	{
		P(semid);
		quisuisje = "pére";//arbitrairement le fils sera le redacteur
		printf("je suis le %s, et je lance l'ecriture \n ",quisuisje); 
		ecriture();
		V(semid);
	}

	//sem_delete(semid);
	//return 0;
}

void lecture()
{
	FILE *f = fopen("./data_file.txt", "r");//ouverture du fichier en lecture
	fgets(data_fils,30,f);
	printf("le pére a dit %s, data_fils");
	fclose(f);
}

void ecriture()
{
	FILE *f = fopen("./data_file.txt", "w"); //ouverture fichier en ecriture
	fprintf(f, "luke, je suis ton pére ");
	fclose(f);
}


void P(int semid) {

  struct sembuf sempar ;

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

  if ( semop(semid,&sempar,1) == -1)
       perror("Erreur lors du down") ;
}


void V(int semid) {

  struct sembuf sempar ;

  sempar.sem_num = 0 ;
  sempar.sem_op = +1 ;
  sempar.sem_flg = 0 ;
  
  if (semop(semid,&sempar,1) ==-1)
    perror("Erreur lors du up") ;
}

void sem_delete(int semid){

  printf("destruction du s\\'emaphore %d\n",semid) ;

  if(semctl(semid,0,IPC_RMID,0) == -1)
    perror("Erreur lors de la destruction du semaphore") ;
}

Cependant à chaque exécution d'un P() ou V(), j'obtient un message "erreur lors du up", ou "erreur lors du down". Savez vous pourquoi ?

Hors ligne

#11 Le 04/04/2013, à 13:25

mortaurat

Re : Sémaphore en C

Help sad

Hors ligne

#12 Le 04/04/2013, à 14:52

telliam

Re : Sémaphore en C

quel est la valeur de errno dans ces cas la?


"- Un intellectuel assis va moins loin qu'un con qui marche."
Maurice Biraud - Un Taxi pour Tobrouk
Michel Audiard

Hors ligne

#13 Le 06/04/2013, à 07:28

mortaurat

Re : Sémaphore en C

En fait dans certain cas mon semid valait -1. j'ai reussi à corriger le probléme je ne sais trop comment...
Maintenant j'ai un probléme classique et pour le moins atypique.
Lorsque je suis dans la phase de lecture, mon programme n’exécute pas le fonction lecture();.
Je le sais car la premiere instruction est un printf("ok1");, et il 'arrive jamais, malgré le fait qu'il affiche bien "je suis le fils et je lance la lecture".
Or il n'y a rien entre le "je suis le fils(..)" et le "ok1", si ce n'est l'appel de la fonction. lorsque je déplace le code de ma fonction dans le main, même probléme.
Notez que mon programme se termine correctement...

	#include <sys/types.h>     /* key_t  */
#include <sys/ipc.h>       /* ftok   */
#include <sys/sem.h>       /* semget, semctl, semop */
#include <sys/stat.h>      /* stat, struct stat  */
#include <stdlib.h>        /* malloc */
#include <stdio.h>         /* perror, printf */
#include <errno.h>         /* errno */

#define PRJVAL  1
#define ID_PROJET 'P'

void lecture();
void ecriture();

void V(int semid);
void P(int semid);
void sem_delete(int semid);

int nb_lecteur = 0;
int nbSem = 1 ;
const char* quisuisje = NULL ;
char data_fils[30]="plop";
int semid;
key_t clef;


void main(int argc, char *argv[])
{		
        pid_t pid;
	clef = ftok(argv[0], ID_PROJET);
	semid = semget(clef,1,IPC_CREAT);//crée le sémaphore
	semctl(semid,0, SETVAL,1);//initialise le sémaphore à 1
	printf("semid = %d \n",semid);

	pid = fork();//va créer un processus fils.
	if(pid == 0)
	{
		P(semid);
		quisuisje = "fils";//arbitrairement le fils sera le lecteur
		printf("je suis le %s, et je lance la lecture\n",quisuisje); 
		lecture();
		printf("le pére a ecrit : %s \n", data_fils);
		V(semid);
		sem_delete(semid);
	}
	else
	{
		P(semid);
		quisuisje = "pére";//arbitrairement le fils sera le redacteur
		printf("je suis le %s, et je lance l'ecriture \n ",quisuisje); 
		ecriture();
		V(semid);
		
	}
	

	
	//return 0;
}


void lecture()
{
	printf("ok1");		
	FILE *fichier = fopen("./data_file.txt", "r");//ouverture du fichier en lecture
	printf("ok2");
	fgets(data_fils,30,fichier);
	printf("le pére a dit %s, data_fils");
	fclose(fichier);
}

void ecriture()
{
	FILE *f = fopen("./data_file.txt", "w"); //ouverture fichier en ecriture
	fprintf(f,"bonjour ");
	fclose(f);
}


void P(int semid) {

  struct sembuf sempar ;

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

  if ( semop(semid,&sempar,1) == -1)
   {
       perror("Erreur lors du down") ;
	printf("erno : %d \n", errno);
    }
}


void V(int semid) {

  struct sembuf sempar ;

  sempar.sem_num = 0 ;
  sempar.sem_op = +1 ;
  sempar.sem_flg = 0 ;
  
  if (semop(semid,&sempar,1) ==-1)
   {
    perror("Erreur lors du up") ;
    printf("erno : %d \n", errno);
    }
}

void sem_delete(int semid){

  printf("destruction du s\\'emaphore %d\n",semid) ;

  if(semctl(semid,0,IPC_RMID,0) == -1)
    perror("Erreur lors de la destruction du semaphore") ;
}

Dernière modification par mortaurat (Le 06/04/2013, à 07:29)

Hors ligne

#14 Le 08/04/2013, à 15:40

mortaurat

Re : Sémaphore en C

Help

Hors ligne

#15 Le 08/04/2013, à 17:20

telliam

Re : Sémaphore en C

au lieu de faire des printf, essaie de faire des ecritures dans un fichier ( et pense bien au fflush), la gestion de la sortie standard est un peu complexe avec les forks.


"- Un intellectuel assis va moins loin qu'un con qui marche."
Maurice Biraud - Un Taxi pour Tobrouk
Michel Audiard

Hors ligne

#16 Le 08/04/2013, à 20:10

mortaurat

Re : Sémaphore en C

Bonsoir,
j'ai remplacé les printf par des écritures fichier. J'avais plein d'erreur à cause des printf de mes fonctions V et P. Du coup j'ai effacé le message d'erreur et ça a l'air de marcher.

Merci

Dernière modification par mortaurat (Le 08/04/2013, à 20:10)

Hors ligne