Précédent   Forum du club des développeurs et IT Pro > C et C++ > C > Réseau
Réseau Forum d'entraide sur la programmation réseau en C
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 01/11/2012, 15h22   #1
problems99
Invité régulier
 
Inscription : août 2010
Messages : 19
Détails du profil
Informations forums :
Inscription : août 2010
Messages : 19
Points : 5
Points : 5
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.
problems99 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/11/2012, 09h35   #2
transgohan
Expert Confirmé
 
Avatar de transgohan
 
Homme Baptiste ROUSSEL
Développeur Temps réel Embarqué
Inscription : janvier 2011
Messages : 1 316
Détails du profil
Informations personnelles :
Nom : Homme Baptiste ROUSSEL
Localisation : France, Territoire de Belfort (Franche Comté)

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

Informations forums :
Inscription : janvier 2011
Messages : 1 316
Points : 2 953
Points : 2 953
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.
transgohan est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/11/2012, 14h43   #3
problems99
Invité régulier
 
Inscription : août 2010
Messages : 19
Détails du profil
Informations forums :
Inscription : août 2010
Messages : 19
Points : 5
Points : 5
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).
problems99 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/11/2012, 16h24   #4
transgohan
Expert Confirmé
 
Avatar de transgohan
 
Homme Baptiste ROUSSEL
Développeur Temps réel Embarqué
Inscription : janvier 2011
Messages : 1 316
Détails du profil
Informations personnelles :
Nom : Homme Baptiste ROUSSEL
Localisation : France, Territoire de Belfort (Franche Comté)

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

Informations forums :
Inscription : janvier 2011
Messages : 1 316
Points : 2 953
Points : 2 953
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.
transgohan est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/11/2012, 16h10   #5
problems99
Invité régulier
 
Inscription : août 2010
Messages : 19
Détails du profil
Informations forums :
Inscription : août 2010
Messages : 19
Points : 5
Points : 5
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
problems99 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/11/2012, 18h51   #6
transgohan
Expert Confirmé
 
Avatar de transgohan
 
Homme Baptiste ROUSSEL
Développeur Temps réel Embarqué
Inscription : janvier 2011
Messages : 1 316
Détails du profil
Informations personnelles :
Nom : Homme Baptiste ROUSSEL
Localisation : France, Territoire de Belfort (Franche Comté)

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

Informations forums :
Inscription : janvier 2011
Messages : 1 316
Points : 2 953
Points : 2 953
Regardes le contenu de la variable errno après le shmat pour vérifier qu'il a bien réussi à attacher la mémoire.

Citation:
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.
transgohan est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/11/2012, 19h57   #7
problems99
Invité régulier
 
Inscription : août 2010
Messages : 19
Détails du profil
Informations forums :
Inscription : août 2010
Messages : 19
Points : 5
Points : 5
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.
problems99 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/11/2012, 08h48   #8
transgohan
Expert Confirmé
 
Avatar de transgohan
 
Homme Baptiste ROUSSEL
Développeur Temps réel Embarqué
Inscription : janvier 2011
Messages : 1 316
Détails du profil
Informations personnelles :
Nom : Homme Baptiste ROUSSEL
Localisation : France, Territoire de Belfort (Franche Comté)

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

Informations forums :
Inscription : janvier 2011
Messages : 1 316
Points : 2 953
Points : 2 953
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.
transgohan est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/11/2012, 16h52   #9
problems99
Invité régulier
 
Inscription : août 2010
Messages : 19
Détails du profil
Informations forums :
Inscription : août 2010
Messages : 19
Points : 5
Points : 5
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.
problems99 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/11/2012, 18h53   #10
transgohan
Expert Confirmé
 
Avatar de transgohan
 
Homme Baptiste ROUSSEL
Développeur Temps réel Embarqué
Inscription : janvier 2011
Messages : 1 316
Détails du profil
Informations personnelles :
Nom : Homme Baptiste ROUSSEL
Localisation : France, Territoire de Belfort (Franche Comté)

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

Informations forums :
Inscription : janvier 2011
Messages : 1 316
Points : 2 953
Points : 2 953
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.
transgohan est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/11/2012, 00h51   #11
problems99
Invité régulier
 
Inscription : août 2010
Messages : 19
Détails du profil
Informations forums :
Inscription : août 2010
Messages : 19
Points : 5
Points : 5
Non c'est en local. Que ce soit à la salle de TP ou chez moi.
problems99 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/11/2012, 08h43   #12
transgohan
Expert Confirmé
 
Avatar de transgohan
 
Homme Baptiste ROUSSEL
Développeur Temps réel Embarqué
Inscription : janvier 2011
Messages : 1 316
Détails du profil
Informations personnelles :
Nom : Homme Baptiste ROUSSEL
Localisation : France, Territoire de Belfort (Franche Comté)

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

Informations forums :
Inscription : janvier 2011
Messages : 1 316
Points : 2 953
Points : 2 953
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.
transgohan est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/11/2012, 15h52   #13
problems99
Invité régulier
 
Inscription : août 2010
Messages : 19
Détails du profil
Informations forums :
Inscription : août 2010
Messages : 19
Points : 5
Points : 5
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
problems99 est déconnecté   Envoyer un message privé Réponse avec citation 10
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 12h11.


 
 
 
 
Partenaires

Hébergement Web