j'utilise linux depuis peu de temps, je l'ai installé pour pouvoir travailler sur les programmes C de temps réel. j'ai installé donc la version suse 8.1 PROFESSIONAL avec la version gcc 3.2 comme c'est indiqué avec la ligne de commande gcc -v :
Reading specs from /usr/lib/gcc-lib/i486-suse-linux/3.2/specs
Configured with: ../configure --enable-threads=posix --prefix=/usr --with-local-prefix=/usr/local --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/usr/lib --enable-languages=c,c++,f77,objc,java,ada --enable-libgcj --with-gxx-include-dir=/usr/include/g++ --with-slibdir=/lib --with-system-zlib --enable-shared --enable-__cxa_atexit i486-suse-linux
Thread model: posix
gcc version 3.2
j'essaie de compiler le programme ci-dessous:
gcc -o shmsem -g -lm shmsem8.c
/* shmsem.c*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <semaphore.h>
#define gotoxy(x,y)printf("\033[%d;%dH",y,x)
caddr_t pg_addr;
sem_t *mysemp;
sem_t *cpt;
int fd;
typedef struct p{
char nom[20];
char prenom[20];
int age;
}FICHE;
void Menu();
void Ecrire();
void shmsem();
void Lire();
void Quitter();
void Menu()
{
gotoxy(30,1);
printf("***** M E N U *****\n");
gotoxy(20,3);
printf("Tapez (1) Ecrire :?\n");
gotoxy(20,5);
printf("Tapez (2) Lire :?\n");
gotoxy(20,7);
printf("Tapez (3) Quitter :?\n");
gotoxy(20,9);
printf("Votre choix : ");
}
/*
prendre le sémaphore encoder puis libérer le sémaphore.
pendant que le processus écrit les autres sont bloqués
*/
void shmsem()
{
int size = sizeof(FICHE);
fd = shm_open("example", O_RDWR|O_CREAT,S_IRWXO|S_IRWXG|S_IRWXU);
if (fd < 0)
{
perror("open error ");
exit(0);
}
if ((ftruncate(fd, size)) == -1)
{
perror("ftruncate failure");
exit(0);
}
pg_addr = (caddr_t) mmap(0, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED,fd, 0);
if (pg_addr == (caddr_t) -1)
{
perror("mmap failure");
exit(0);
}
/*le sémaphore initial*/
mysemp = sem_open("mysemp", O_CREAT | O_RDWR, 0644, 1);
if (mysemp == (void *)-1)
{
perror("sem_open() failed ");
}
/*le sémaphore compteur*/
cpt = sem_open("mycpt", O_CREAT | O_RDWR, 0644, 0);
if (cpt == (void *)-1)
{
perror("sem_open() failed ");
}
sem_post(cpt);
}
void Ecrire()
{
FICHE nouveau;
int a;
char n[20], p[20];
/* ATTENTE DU SEMA : SEM_WAIT */
printf ("En attente.....\n");
sem_wait(mysemp);
printf ("ECRITURE\n");
fflush(stdin);
printf("Nom:");
scanf("%s",&n);
fflush(stdin);
printf("Prenom:");
scanf("%s",&p);
printf("Age:");
scanf("%d",&a);
strcpy(nouveau.nom, n);
strcpy(nouveau.prenom, p);
nouveau.age=a;
memcpy(pg_addr, &nouveau, sizeof(FICHE));
/* LIBERATION DU SEMA : SEM_POST */
sem_post(mysemp);
}
/*
prendre le sémaphore, lire, afficher et libérer le sémaphore.
pendant que le processus lit les autres sont bloqués
*/
void Lire()
{
FICHE pers;
printf ("LECTURE\n");
/* ATTENTE DU SEMA : SEM_WAIT */
printf ("En attente......\n");
sem_wait(mysemp);
memcpy(&pers, pg_addr, sizeof(FICHE));
printf ("Nom : %s\t Prenom : %s\t Age : %d\n",pers.nom,pers.prenom,pers.age);
/* LIBERATION DU SEMA : SEM_POST */
sem_post(mysemp);
fflush(stdin);
getchar();
}
/*
le dernier processus qui reste doit détruire toutes les ressources :
mémoire partagée et sémaphore.
*/
void Quitter()
{
int val;
sem_wait(cpt);
sem_getvalue(cpt,&val);
if(val==0)
{
sem_close(mysemp);
sem_close(cpt);
sem_unlink ("mysemp");
sem_unlink("mycpt");
close(fd);
shm_unlink("example");
}
}
main()
{
char car;
shmsem();
do
{
printf("\033[2J");
Menu();
/* ignore tous les caracteres non alphanumeriques */
while(!isalnum(car=getchar()));
switch (car)
{
case '1': Ecrire();
break;
case '2': Lire();
break;
case '3': Quitter();
break;
default: fprintf(stderr,"%c: commande inconnue !\n",car);
}
}while (car != 'q');
getchar();
}
mais à la compilation j'obtiens les ereeurs suivantes:
/tmp/ccIlvtPs.o: dans la fonction « shmsem »:
/home/karimi/psindus/labo8/shmsem8.c:55: référence indéfinie vers « shm_open »
/home/karimi/psindus/labo8/shmsem8.c:74: référence indéfinie vers « sem_open »
/home/karimi/psindus/labo8/shmsem8.c:80: référence indéfinie vers « sem_open »
/home/karimi/psindus/labo8/shmsem8.c:85: référence indéfinie vers « sem_post »
/tmp/ccIlvtPs.o: dans la fonction « Ecrire »:
/home/karimi/psindus/labo8/shmsem8.c:94: référence indéfinie vers « sem_wait »
/home/karimi/psindus/labo8/shmsem8.c:112: référence indéfinie vers « sem_post »
/tmp/ccIlvtPs.o: dans la fonction « Lire »:
/home/karimi/psindus/labo8/shmsem8.c:124: référence indéfinie vers « sem_wait »
/home/karimi/psindus/labo8/shmsem8.c:129: référence indéfinie vers « sem_post »
/tmp/ccIlvtPs.o: dans la fonction « Quitter »:
/home/karimi/psindus/labo8/shmsem8.c:140: référence indéfinie vers « sem_wait »
/home/karimi/psindus/labo8/shmsem8.c:141: référence indéfinie vers « sem_getvalue »
/home/karimi/psindus/labo8/shmsem8.c:144: référence indéfinie vers « sem_close »
/home/karimi/psindus/labo8/shmsem8.c:145: référence indéfinie vers « sem_close »
/home/karimi/psindus/labo8/shmsem8.c:146: référence indéfinie vers « sem_unlink »
/home/karimi/psindus/labo8/shmsem8.c:147: référence indéfinie vers « sem_unlink »
/home/karimi/psindus/labo8/shmsem8.c:149: référence indéfinie vers « shm_unlink »
collect2: ld returned 1 exit status
apparemment gcc ne recoonait pas les fonctions pour la mémoire partagée des fichiers en-têtes <sys/types.h> et <sys/mman.h>
ou alors est-ce un problème du linker j'ai fait le tour d'internet pour voir si quelqu'un avait eu précédemment ce genre de problèmes, mes recherches étaient vaines alors je m'adresses à vous dans l'espoir que vous puissiez m'aider s'il vous plaît et merci encore
# man shm_open
Posté par Frédéric Lopez . Évalué à 5.
Utilise la commande suivante et ça devrait compiler :
gcc -o shmsem -g -lm -lrt shmsem8.c
# En passant...
Posté par alf . Évalué à 3.
Si on la définit de la manière que tu as faite
alors on retombe sur les "anciennes" déclarations (au sens C), et aucun contrôle n'est fait par le compilateur sur les paramètres envoyés: voir la phrase 6.7.5.3.p14 du n1124:
comparée avec 6.7.5.3.p10:
Donc avec tes protoypes tu as le droit d'appeler ensuite les fonctions avec des paramètres quelquonques, ce qui diminue l'utilité du protoype...
- - - - - - -
Les deux seules manières portables de définir main sont int main(void)et int main(int argc, char **argv) (ou des définitions compatibles, comme char *argv[]). Le reste est dépendant de la plate-forme.
- - - - - - -
Non. getchar() renvoie un int. Sa valeur de retour exacte est:
- soit le prochain caractère en unsigned char;
- soit EOF si le flux est "fini".
cf. 7.19.7.1p2
7.19.7.1 p3:
et 7.19.1p3
Donc, envoyer le résultat de getchar (qui est un équivalent de getc(stdin), lui-même (quasi) équivalent à fgetc(stdin)) dans un char peut causer une perte d'information si ton implémentation définit le char comme signé.
En pratique, EOF peut valoir par exemple -1, qui correspond parfois à la valeur signed char du caractère ÿ, si je me souviens bien. Ce qui signifie que, si tu lis ce ÿ avec ton code (ou d'autres caractères suivant l'environnement), sa valeur unsigned déborde la capacité du signed char, et retombe sur -1 par les règles de conversions entières. Tu croiras voir un EOF, donc isalnum() renvoie faux, et le while le bouffera sans broncher... Dans ton cas, ce n'est pas forcément grave, mais l'erreur peut porter à conséquence dans d'autres contextes.
[^] # Re: En passant...
Posté par alf . Évalué à 3.
. (c'est moi qui souligne).
Et mon commentaire est incomplet: la perte d'information arrivera même si le char est non signé (vu que EOF est une valeur qui se rajoute à l'ensemble des valeurs valides des caractères).
[^] # Re: En passant...
Posté par B. franck . Évalué à 2.
fait fi de la portabilité, qui n'utilise pas les fonctions standards comme définies dans la documentation, qui n'initialise pas ses variables avant de les utiliser, qui utilise des pointeurs avant de regarder s'ils pointent vers quelquechose, qui est fortement "buffer-overflow-able" est du code crade ? :))
[^] # Re: En passant...
Posté par nas . Évalué à 1.
[^] # Re: En passant...
Posté par alf . Évalué à 2.
est très moche. Caster -1 en pointeur, c'est assez ignoble (au passage, c'est non portable). mmap() renvoie MAP_FAILED en cas d'erreur (suivant POSIX; après si l'implémentation n'est pas conforme, c'est autre chose...).
De plus, exit(0) pour signaler une erreur ! EXIT_FAILURE sert à ça.
Qui plus est, faire un exit() alors qu'on a soi-même défini une fonction Quitter, c'est illogique.
En relisant un peu mieux, on a aussi:
- fflush(stdin);, cf. http://c-faq.com/stdio/stdinflush2.html .
- scanf(), cf. http://mapage.noos.fr/emdel/notes.htm#saisie
- int size = sizeof(FICHE);, alors que sizeof renvoie un size_t, et que c'est justement ce que mmap() est censé recevoir...
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.