Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 13 sur 13
  1. #1
    Invité régulier
    Inscrit en
    août 2010
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : août 2010
    Messages : 19
    Points : 6
    Points
    6

    Par défaut Sémaphores et mémoire partagée (interaction client - serveur)

    Bonjour à tous,


    Pour un exercice, je dois transférer une chaine de caractères d'un client vers un serveur, ce dernier transforme les minuscules en majuscule et la renvoie au client, tout ça en utilisant des sémaphores et une mémoire partagée.


    A mon avis, ce qui coince, c'est que je n'utilise pas les sémaphores au bon moment. Les fonctions down, up et initialize sont correctes car je les ai déjà utilisées dans un exercice précédent.

    Si vous pouviez jeter un coup d'oeil, ce serait sympa.

    Client :
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
     
    # include <stdio.h>
    # include <stdlib.h>
    # include <unistd.h>
    # include <sys/wait.h>
    # include <sys/types.h>
    # include <signal.h>
    # include <sys/time.h>
    # include <sys/sem.h>
    # include <sys/types.h>
    # include <sys/ipc.h>
    # include <semaphore.h>
    # include <sys/shm.h>
     
    int down(int sem_id, int sem_num)
    {
    	struct sembuf sem_op;
    	sem_op.sem_num=sem_num;
    	sem_op.sem_op=-1;
    	sem_op.sem_flg=0;
     
    	if(semop(sem_id, &sem_op, 1) == -1) return -1;
    	else return 0;
    }
     
    int up(int sem_id, int sem_num)
    {
    	struct sembuf sem_op;
    	sem_op.sem_num=sem_num;
    	sem_op.sem_op=+1;
    	sem_op.sem_flg=0;
     
    	if(semop(sem_id, &sem_op,1) == -1) return -1;
    }
     
    int main (){
    	int i=0, semid, shmid;
    	char *string;	
     
     
    	semid=semget(1234,1,IPC_CREAT|0660);
    	if(semid==-1)
    	{
    		perror("Erreur lors du semget");
    		exit(-1);
    	}
     
    	shmid=shmget(13245,80*sizeof(char),IPC_CREAT|0660);	// Creation de la memoire partagee
     
    	if(shmid==-1)
    	{
    		perror("Erreur lors du shmget");
    		exit(-1);
    	}	
     
    	string=(char*)shmat(shmid,NULL,SHM_W|SHM_R);	// Attachement de la memoire partagee dans le pointeur memoire
     
    	down(semid,0);		
    	scanf("%s", string);			
    	printf("%s \n", string);
    	up(semid,0);
     
     
     
     
     
    	return 0 ;
     
    }
    Serveur :
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
     
    # include <stdio.h>
    # include <stdlib.h>
    # include <unistd.h>
    # include <sys/wait.h>
    # include <sys/types.h>
    # include <signal.h>
    # include <sys/time.h>
    # include <sys/sem.h>
    # include <sys/types.h>
    # include <sys/ipc.h>
    # include <semaphore.h>
    # include <sys/shm.h>
     
     
    union semun {
                 int val; 
                 struct semid_ds *buf;
                 unsigned short *array;
                 struct seminfo *__buf;
    };
     
    int initialize(int sem_id, int sem_num, int init)
    {
    	union semun semunion;
    	semunion.val=init;
    	if(semctl(sem_id,sem_num,SETVAL,semunion) == -1) return -1;
    	else return 0;	
    }
     
    int down(int sem_id, int sem_num)
    {
    	struct sembuf sem_op;
    	sem_op.sem_num=sem_num;
    	sem_op.sem_op=-1;
    	sem_op.sem_flg=0;
     
    	if(semop(sem_id, &sem_op, 1) == -1) return -1;
    	else return 0;
    }
     
    int up(int sem_id, int sem_num)
    {
    	struct sembuf sem_op;
    	sem_op.sem_num=sem_num;
    	sem_op.sem_op=+1;
    	sem_op.sem_flg=0;
     
    	if(semop(sem_id, &sem_op,1) == -1) return -1;
    }
     
    int main (){
    	int i=0, semid, shmid;			
    	char *string;
     
     
    	semid=semget(1234,1,IPC_CREAT|0660);		// Creation d'un groupe contenant 2 semaphore	
     
    	if(semid==-1)
    	{
    		perror("Erreur lors du semget");
    		exit(-1);
    	}		
     
    	initialize(semid,1,0);	
     
     
    	shmid=shmget(13245,80*sizeof(char),IPC_CREAT | 0660);	// Creation de la memoire partagee
     
    	if(shmid==-1)
    	{
    		perror("Erreur lors du shmget");
    		exit(-1);
    	}
     
    	string=(char*)shmat(shmid,NULL,SHM_W|SHM_R);	// Attachement de la memoire partagee dans le pointeur memoire
     
     
     
     
    	while(1){
     
    		printf("serveur %s \n", string); // 2 lignes de test
    		sleep(3);
                    //down(semid,0);     // Vrai code
    		/*for (i=0; i<sizeof(string); i++)
    			string[i]=toupper(string[i]);
    		for (i=0; i<sizeof(string); i++)
    			printf("%c", string[i]);	
    		printf("\n");
    		//up(semid,0);	*/
    		}
     
     
     
     
    	shmdt(string);		// Detachement de la memoire partagee	
    	shmctl(shmid,IPC_RMID,NULL);	// Suppression de la memoire partagee
    	semctl(semid,0,IPC_RMID,NULL);	// Suppression du groupe de semaphores
     
    	return 0 ;
     
    }
    Comme vous l'avez remarqué, je ne me suis pas encore soucié du retour du message. Merci de votre aide.

  2. #2
    Expert Confirmé Sénior
    Avatar de transgohan
    Homme Profil pro Baptiste ROUSSEL
    Développeur Temps réel Embarqué
    Inscrit en
    janvier 2011
    Messages
    1 754
    Détails du profil
    Informations personnelles :
    Nom : Homme Baptiste ROUSSEL
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Temps réel Embarqué

    Informations forums :
    Inscription : janvier 2011
    Messages : 1 754
    Points : 4 726
    Points
    4 726

    Par défaut

    Soucies toi en premier lieu du retour de tes fonctions, cela renvoie peut être -1 et dans ce cas regardes l'erreur dans errno.
    Toujours se souvenir que la majorité des ennuis viennent de l'espace occupé entre la chaise et l'écran de l'ordinateur.

  3. #3
    Invité régulier
    Inscrit en
    août 2010
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : août 2010
    Messages : 19
    Points : 6
    Points
    6

    Par défaut

    Tu veux parler pour shmat ? Le reste ne renvoie pas d'erreur.

    Pour le client,


    Code :
    1
    2
    3
    4
    	down(semid,0);		
    	scanf("%s", string);			
    	printf("%s \n", string);
    	up(semid,0);
    La seule chance pour que ça marche, c'est de mettre down et up en commentaire. Si j'en laisse un des deux voir les deux, on dirait que le programme attend quelque chose, le printf ne marche pas juste après la saisie du scanf (qui je pense, ne marche pas non plus).

  4. #4
    Expert Confirmé Sénior
    Avatar de transgohan
    Homme Profil pro Baptiste ROUSSEL
    Développeur Temps réel Embarqué
    Inscrit en
    janvier 2011
    Messages
    1 754
    Détails du profil
    Informations personnelles :
    Nom : Homme Baptiste ROUSSEL
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Temps réel Embarqué

    Informations forums :
    Inscription : janvier 2011
    Messages : 1 754
    Points : 4 726
    Points
    4 726

    Par défaut

    Je parlais du retour de tes fonctions down et up et donc de semop().

    Aussi tu as un souci avec l'utilisation de scanf, c'est l'adresse que tu dois lui passer => &string
    Toujours se souvenir que la majorité des ennuis viennent de l'espace occupé entre la chaise et l'écran de l'ordinateur.

  5. #5
    Invité régulier
    Inscrit en
    août 2010
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : août 2010
    Messages : 19
    Points : 6
    Points
    6

    Par défaut

    J'avance j'avance

    Mes sémaphores sont ok, les processus affichent bien leur message à tour de rôle au bon moment.

    Par contre, le serveur ne reçoit pas la modification du client et vice versa.

    Voilà le code travaillé (uniquement la partie modifiée) :

    Client :

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    	string=(char*)shmat(shmid,NULL,SHM_W|SHM_R);	// Attachement de la memoire partagee dans le pointeur memoire
     
    	printf("%d\n", __LINE__);
    	down(semid,0);
    	printf("%d\n", __LINE__);		
    	scanf("%s", &string);
    	printf("%d\n", __LINE__);			
    	printf("%s \n", &string);
    	printf("%d\n", __LINE__);
    	up(semid,0);
    	down(semid,0);
    	printf("%s \n", &string);
    	up(semid,0);
    Serveur

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    string=(char*)shmat(shmid,NULL,SHM_W|SHM_R);	// Attachement de la memoire partagee dans le pointeur memoire
     
     
    	sleep(5);	
    	down(semid,0);		
    	printf("serveur %s \n", &string);
    	for (i=0; i<sizeof(string); i++)
    		string[i]=toupper(string[i]);
    	for (i=0; i<sizeof(string); i++)
    		printf("%c", string[i]);	
    	printf("\n");
    	up(semid,0);	
    	down(semid,0);
    	up(semid,0);
    Donc, si j'entre "test" au client, il va bien afficher test au printf.
    Le serveur quand à lui, affichera "serveur "
    Et quand ça sera de nouveau au tour du client, il réaffichera "test"

    La mémoire n'est pas partagée en fait. Est-ce que je dois attacher la mémoire de mon serveur après le down(semid, 0) ?


    Merci de ton aide

  6. #6
    Expert Confirmé Sénior
    Avatar de transgohan
    Homme Profil pro Baptiste ROUSSEL
    Développeur Temps réel Embarqué
    Inscrit en
    janvier 2011
    Messages
    1 754
    Détails du profil
    Informations personnelles :
    Nom : Homme Baptiste ROUSSEL
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Temps réel Embarqué

    Informations forums :
    Inscription : janvier 2011
    Messages : 1 754
    Points : 4 726
    Points
    4 726

    Par défaut

    Regardes le contenu de la variable errno après le shmat pour vérifier qu'il a bien réussi à attacher la mémoire.

    S’il réussit, shmat() renvoie l’adresse d’attachement du segment de mémoire partagée. En cas d’échec (void *) −1 est renvoyé, et errno contient le code d’erreur.
    Toujours se souvenir que la majorité des ennuis viennent de l'espace occupé entre la chaise et l'écran de l'ordinateur.

  7. #7
    Invité régulier
    Inscrit en
    août 2010
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : août 2010
    Messages : 19
    Points : 6
    Points
    6

    Par défaut

    Tiens, je ne connaissais pas errno.

    Je ne sais pas si je l'ai bien fait :

    Code :
    1
    2
    3
    string=(char *) shmat(shmid, NULL, SHM_W|SHM_R);
    if (string==-1) 
    printf("Code de l'erreur : %d \n", errno);
    Donc soit je l'ai mal faite (je m'embrouille parfois avec les pointeurs), soit ça réussit et ne passe pas dedans.

  8. #8
    Expert Confirmé Sénior
    Avatar de transgohan
    Homme Profil pro Baptiste ROUSSEL
    Développeur Temps réel Embarqué
    Inscrit en
    janvier 2011
    Messages
    1 754
    Détails du profil
    Informations personnelles :
    Nom : Homme Baptiste ROUSSEL
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Temps réel Embarqué

    Informations forums :
    Inscription : janvier 2011
    Messages : 1 754
    Points : 4 726
    Points
    4 726

    Par défaut

    string est un char* donc ta condition ne sera jamais valide.
    Le plus simple reste encore d'afficher errno avant l'appel de la fonction et après.
    C'est juste pour le debug et t'as pas à te soucier de comment caster le retour ou comment le comparer.
    Toujours se souvenir que la majorité des ennuis viennent de l'espace occupé entre la chaise et l'écran de l'ordinateur.

  9. #9
    Invité régulier
    Inscrit en
    août 2010
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : août 2010
    Messages : 19
    Points : 6
    Points
    6

    Par défaut

    En effet, tu a raison, j'ai errno=22 dans le code serveur !

    Cependant, errno passe de 0 à 22 dans la fonction initialize(), plus précisément :

    Code :
    1
    2
    if(semctl(sem_id,sem_num,SETVAL,semunion) == -1) return -1;	
    	else return 0;
    (ligne 27 et 28 du serveur).

    Mais je ne vois pas en quoi ça affecte ma mémoire partagée. Surtout que mes sémaphores fonctionnent bien.

    En remettant errno=0 avant le shmat, il ne change pas de valeur après.

  10. #10
    Expert Confirmé Sénior
    Avatar de transgohan
    Homme Profil pro Baptiste ROUSSEL
    Développeur Temps réel Embarqué
    Inscrit en
    janvier 2011
    Messages
    1 754
    Détails du profil
    Informations personnelles :
    Nom : Homme Baptiste ROUSSEL
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Temps réel Embarqué

    Informations forums :
    Inscription : janvier 2011
    Messages : 1 754
    Points : 4 726
    Points
    4 726

    Par défaut

    Cette erreur indique que le système n'a pas assez de semaphore.
    Tu travailles en local ou bien sur un serveur utilisé par d'autres ?
    Je dis ça car j'ai eu des TPs durant mes études où il était bien difficile de faire tourner un quelconque programme en raison des étudiants ne libérant pas correctement la mémoire... Donc seuls les étudiants du lundi (après reboot du weekend) pouvaient exécuter les TPs correctement.
    Toujours se souvenir que la majorité des ennuis viennent de l'espace occupé entre la chaise et l'écran de l'ordinateur.

  11. #11
    Invité régulier
    Inscrit en
    août 2010
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : août 2010
    Messages : 19
    Points : 6
    Points
    6

    Par défaut

    Non c'est en local. Que ce soit à la salle de TP ou chez moi.

  12. #12
    Expert Confirmé Sénior
    Avatar de transgohan
    Homme Profil pro Baptiste ROUSSEL
    Développeur Temps réel Embarqué
    Inscrit en
    janvier 2011
    Messages
    1 754
    Détails du profil
    Informations personnelles :
    Nom : Homme Baptiste ROUSSEL
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Temps réel Embarqué

    Informations forums :
    Inscription : janvier 2011
    Messages : 1 754
    Points : 4 726
    Points
    4 726

    Par défaut

    Tu as une commande normalement permettant de visualiser les objets partagés.
    J'ai pas retrouvé ça, mais si tu as un cours cela devrait être abordé.
    Regardes donc grâce à cette commande si tu n'as pas une foule d'objets utilisés, ou peut être créés et abandonnés.
    Car après pour augmenter le nombre de sémaphore disponible il faut soit en libérer, soit recompiler le noyau en augmentant le nombre si je ne m'abuse.

    Toujours est-il qu'il est bizarre que tu obtiennes cet errno sur semctl, cette fonction n'a pas vocation à créer une sémaphore. :/
    Toujours se souvenir que la majorité des ennuis viennent de l'espace occupé entre la chaise et l'écran de l'ordinateur.

  13. #13
    Invité régulier
    Inscrit en
    août 2010
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : août 2010
    Messages : 19
    Points : 6
    Points
    6

    Par défaut

    Voilà c'est réglé, il y avait juste un problème de IPC_CREAT dans le client et des & en trop dans les scanf et prinf car ce sont des pointeurs.

    Voilà le code final :

    Client

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    # include <stdio.h>
    # include <stdlib.h>
    # include <unistd.h>
    # include <sys/wait.h>
    # include <sys/types.h>
    # include <signal.h>
    # include <sys/time.h>
    # include <sys/sem.h>
    # include <sys/types.h>
    # include <sys/ipc.h>
    # include <semaphore.h>
    # include <sys/shm.h>
    # include <errno.h>
     
    int down(int sem_id, int sem_num)
    {
    	struct sembuf sem_op;
    	sem_op.sem_num=sem_num;
    	sem_op.sem_op=-1;
    	sem_op.sem_flg=0;
     
    	if(semop(sem_id, &sem_op, 1) == -1) {
    		printf("Erreur lors du down \n");	
    		return -1;
    	}
    	else return 0;
    }
     
    int up(int sem_id, int sem_num)
    {
    	struct sembuf sem_op;
    	sem_op.sem_num=sem_num;
    	sem_op.sem_op=+1;
    	sem_op.sem_flg=0;
     
    	if(semop(sem_id, &sem_op,1) == -1) {
    		printf("Erreur lors du up\n");	
    		return -1;
    	}	
    }
     
    int main (){
    	int i=0, semid, shmid;
    	char *string;	
     
     
     
    	pid_t pid;
     
    	semid=semget(1234,1,0660);
    	if(semid==-1)
    	{
    		perror("Erreur lors du semget");
    		exit(-1);
    	}
     
    	shmid=shmget(13245,80*sizeof(char),0660);	// Creation de la memoire partagee
     
    	if(shmid==-1)
    	{
    		perror("Erreur lors du shmget");
    		exit(-1);
    	}	
     
    	string=(char*)shmat(shmid,NULL,SHM_W|SHM_R);	// Attachement de la memoire partagee dans le pointeur memoire
     
     
    	scanf("%s", string);				
    	printf("%s\n", string);	
    	up(semid,0);
    	down(semid,0);
    	printf("%s\n",string);
    	up(semid,0);
     
     
     
     
    	return 0 ;
     
    }
    Serveur
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
     
    # include <stdio.h>
    # include <stdlib.h>
    # include <unistd.h>
    # include <sys/wait.h>
    # include <sys/types.h>
    # include <signal.h>
    # include <sys/time.h>
    # include <sys/sem.h>
    # include <sys/types.h>
    # include <sys/ipc.h>
    # include <semaphore.h>
    # include <sys/shm.h>
    # include <errno.h>
     
     
    union semun {
                 int val; 
                 struct semid_ds *buf;
                 unsigned short *array;
                 struct seminfo *__buf;
    };
     
    int initialize(int sem_id, int sem_num, int init)
    {
    	union semun semunion;
     
    	semunion.val=init;	
    	if(semctl(sem_id,sem_num,SETVAL,semunion) == -1) return -1;	
    	else return 0;	
    }
     
    int down(int sem_id, int sem_num)
    {
    	struct sembuf sem_op;
    	sem_op.sem_num=sem_num;
    	sem_op.sem_op=-1;
    	sem_op.sem_flg=0;
     
    	if(semop(sem_id, &sem_op, 1) == -1) return -1;
    	else return 0;
    }
     
    int up(int sem_id, int sem_num)
    {
    	struct sembuf sem_op;
    	sem_op.sem_num=sem_num;
    	sem_op.sem_op=+1;
    	sem_op.sem_flg=0;
     
    	if(semop(sem_id, &sem_op,1) == -1) return -1;
    }
     
    int main (){
    	int i=0, semid, shmid;			
    	char *string;
     
     
    	semid=semget(1234,1,IPC_CREAT|0660);		// Creation d'un groupe contenant 2 semaphore	
     
    	if(semid==-1)
    	{
    		perror("Erreur lors du semget");
    		exit(-1);
    	}	
     
     
    	initialize(semid,0,0);	
     
    	shmid=shmget(13245,80*sizeof(char),IPC_CREAT | 0660);	// Creation de la memoire partagee
     
    	if(shmid==-1)
    	{
    		perror("Erreur lors du shmget");
    		exit(-1);
    	}
     
     
    	string=(char*)shmat(shmid,NULL,SHM_W|SHM_R);	// Attachement de la memoire partagee dans le pointeur memoire
     
    	down(semid,0);		
    	printf("serveur %s \n", &string);
    	for (i=0; i<sizeof(string); i++)
    		string[i]=toupper(string[i]);
    	for (i=0; i<sizeof(string); i++)
    		printf("%c", string[i]);	
    	printf("\n");
    	up(semid,0);	
    	down(semid,0);
    	up(semid,0);
     
    	shmdt(string);		// Detachement de la memoire partagee	
    	shmctl(shmid,IPC_RMID,NULL);	// Suppression de la memoire partagee
    	semctl(semid,0,IPC_RMID,NULL);	// Suppression du groupe de semaphores
     
    	return 0 ;
     
    }
    Encore merci

+ Répondre à la discussion
Cette discussion est résolue.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •