IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau C Discussion :

Verrouillage d'un fifo accessible par plusieurs prog


Sujet :

Réseau C

  1. #1
    Membre éclairé
    Homme Profil pro
    Analyste/développeur Java EE
    Inscrit en
    Janvier 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste/développeur Java EE

    Informations forums :
    Inscription : Janvier 2005
    Messages : 376
    Par défaut Verrouillage d'un fifo accessible par plusieurs prog
    Bonjour,
    je dois créer une mini application "client-serveur" avec des fifos (pas des sockets, des fifos). Pour l'instant, ça fonctionne en mono utilisateur et je dois le passer en multi-utilisateurs.

    Problème: le fifo du serveur (auquel j'envoie les requêtes) devient une ressource critique. Je pensais à le verrouiller du coté client:
    -verrouillage écriture (pour les autres clients)
    -écriture de la requete
    -déverrouillage

    Cela à l'aide de la fonction fcntl(). Je me demandais si mon raisonnement était possible. Il me semble que non, si je verrouille en écriture, je ne saurais plus écrire dans le fifo avant le déverouillage. Comment pourrais-je faire?

    Merci d'avance

  2. #2
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Je t'aurais bien dit une sémaphore mais je ne pense pas qu'on puisse les utiliser en dehors de l'utilisation des Threads, il faut sinon créer un système similaire mais sans Thread alors Bien sûr, ce n'est qu'une idée en passant donc bloquer à la lecture pendant l'écriture et vice versa.
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  3. #3
    Membre éclairé
    Homme Profil pro
    Analyste/développeur Java EE
    Inscrit en
    Janvier 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste/développeur Java EE

    Informations forums :
    Inscription : Janvier 2005
    Messages : 376
    Par défaut
    Dans le programme client, je n'utilise pas de threads. Inutile puisqu'on lance plusieurs fois le même prog. C'est dans le serveur que j'utilise les threads, mais je n'ai pas besoin de verrouillage là-bas. En regardant sur internet, j'ai essayé ceci (dans le client):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
        // Ouvreture du fifo requête
        fdW = open("/tmp/requete", O_WRONLY);
        if (fdW == -1) {
          perror("Erreur d'ouverture du fichier serveur");
          return -1;
        }
     
        //Verrouillage
        verrou.l_type = F_RDLCK; //bloque l'écriture aux autres processus (donc autres clients)
        verrou.l_whence = 0;
        verrou.l_start = 0;
        verrou.l_len = 0;
     
        if (fcntl(fdW, F_SETLKW, &verrou)== -1){
          perror("Erreur de verrouillage");
        }
     
        //Envoi de la requête
        nbWrite = write(fdW, &requete, sizeof(requete));
        if (nbWrite < sizeof(requete)) {
          perror("Erreur d'écriture");
        }
     
        //Déverrouillage
        verrou.l_type = F_UNLCK; 
        if (fcntl(fdW, F_SETLKW, &verrou)== -1){
          perror("Erreur de deverrouillage");
        }
     
        close(fdW);
    Mais là, il me dit: Erreur de verrouillage: Bad file descriptor

    Pourtant après l'affichage de l'erreur, il m'affiche bien la réponse, donc la requête a bien été envoyé et traitée par le serveur ==> le descripteur est bon.

    Je n'ai jamais fait de verrouillage avant, mais j'ai l'impression que ça vient du fait que ce soit pas un fichier, mais un fifo (pipe). Je me trompe?

  4. #4
    Membre émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut
    Juste comme ça histoire de dire ... les fifos (pipe) ça ne s'ouvre pas avec "popen()" au lieu de "open()" ?

  5. #5
    Membre éclairé
    Homme Profil pro
    Analyste/développeur Java EE
    Inscrit en
    Janvier 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste/développeur Java EE

    Informations forums :
    Inscription : Janvier 2005
    Messages : 376
    Par défaut
    popen retourne un FILE * et pour mes opérations de lecture/écriture, j'ai besoin d'un descripteur (int).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    FILE *popen(const char *command, const char *type);
     
    int open(const char *pathname, int flags);
    int open(const char *pathname, int flags, mode_t mode);

  6. #6
    Membre émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut
    Pourquoi ne pas utiliser "fileno()" dans ce cas pour récupérer un handle int à partir du FILE* ?

  7. #7
    Membre éclairé
    Homme Profil pro
    Analyste/développeur Java EE
    Inscrit en
    Janvier 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste/développeur Java EE

    Informations forums :
    Inscription : Janvier 2005
    Messages : 376
    Par défaut
    Je viens d'essayer en remplaçant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fdW = open("/tmp/requete", O_WRONLY);
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fdW = fileno(popen("/tmp/requete","w"));
    Et j'obtiens la même erreur bad file descriptor

    Mais je pense que les deux bouts de codes sont équivalents.

  8. #8
    Membre émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut
    Je disais une bétise, pour ouvrir un tube il faut utiliser la fonction "pipe()".

  9. #9
    Membre éclairé
    Homme Profil pro
    Analyste/développeur Java EE
    Inscrit en
    Janvier 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste/développeur Java EE

    Informations forums :
    Inscription : Janvier 2005
    Messages : 376
    Par défaut
    La fonction pipe() ouvre un pipe anonyme, donc uniquement accessible dans un même programme et ne crée pas de fichier.

    La fonction mkfifo() ouvre un pipe nommé (fifo) et crée en même temps un fichier de type pipe, c'est via ce fichier que je fais mes échanges entre les progs clients et le prog serveur.

    Le fifo que j'utilise ci-dessus est créé dans le programme serveur qui est lancé en background avant le(s) client(s). Comme ceci dans serveur.c:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // Création du tube nommé du serveur
      if ((mkfifo("/tmp/requete", 00700) < 0) && (errno != EEXIST)) {
        perror("Erreur à la création du fifo");
        return -1;
      }

  10. #10
    Membre émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut
    Je suppose que tu as déjà vérifié que ton tube /tmp/requete est bien crée en faisant un "ls".

    Je en connais pas trop Linux, mais est-ce que tu as vérifié s'il n'existe pas un flag à fctnl du type "SHARED_OPEN" ; car j'ai vraiment l'impression que c'est ton lock qui génère le "Bad Descriptor".

    Au fait tu est bien sur que le "Bad Descriptor" à lieu lors de l'open ?

    Enfin, sous Linux un tube est un fichier comme un autre, donc il devrait être possible de le locker (sauf indication contraire dans les pages de man).

  11. #11
    Membre éclairé
    Homme Profil pro
    Analyste/développeur Java EE
    Inscrit en
    Janvier 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste/développeur Java EE

    Informations forums :
    Inscription : Janvier 2005
    Messages : 376
    Par défaut
    ls /tmp/ j'ai testé mes fifos existent bien.

    L'open se passe sans problème autrement il me retournerait une erreur avant le verrouillage.

    La "nouvelle" fonction pour moi dans celle citées, c'est fnctl. Je ne la maîtrise pas, et je n'ai pas trouvé assez d'exemples de verrouillage, beaucoup de page man sur google mais pas assez d'exemples concrets (je préfère le concret pour comprendre).

  12. #12
    Membre émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut
    Ton pipe /tmp/request il est mono ou bi-directionnel ?

    Car je viens de lire que les verrous en écriture sont exclusifs, donc pas possible de faire un lock à la fois sur le serveur et le client.

    De plus sur AIX http://www.unet.univie.ac.at/aix/lib...trf1/fcntl.htm, visiblement fcntl ne peut pas être utilisé pour locker une fifo.

    Peut-être que sur Linux c'est pareil. Dommage !

  13. #13
    Membre éclairé
    Homme Profil pro
    Analyste/développeur Java EE
    Inscrit en
    Janvier 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste/développeur Java EE

    Informations forums :
    Inscription : Janvier 2005
    Messages : 376
    Par défaut
    Voici des info sur le retour d'erreur:
    EBADF fd is not an open file descriptor, or the command was F_SETLK or F_SETLKW and the file descriptor open mode doesn’t match with the type of lock requested.
    Donc ce serait un problème de paramétrage du verrou...

    Edit: le fifo en question est mono-directionnel: client ->serveur. J'en utilise d'autres pour les échanges du serveur vers le client

    Pour le verrouillage, je me base sur ce pdf (chapitre 12).

  14. #14
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    d'après ce que tu dis du diagnostic et du man, ce serait pas qu'il faut rajouter un flag à O_WRONLY pour open ??

    Je suis pas sur Linux, là, mais tu dois avoir un flag qui permet le SETFLK..

  15. #15
    Membre éclairé
    Homme Profil pro
    Analyste/développeur Java EE
    Inscrit en
    Janvier 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste/développeur Java EE

    Informations forums :
    Inscription : Janvier 2005
    Messages : 376
    Par défaut
    Je ne comprends pas bien ce que tu veux dire avec le O_WRONLY, j'ouvre le fifo comme cela pour le moment. Le problème doit venir du verrouillage.

    Si je comprends bien ce que je fais, voici ce qui devrait se passer si on a 2 clients en même temps:
    • lancement du serveur en background, création du fifo (en boucle)
    • lancement du premier client: (en boucle)
      • ouverture du fifo en écriture
      • verrouillage de l'écriture pour les autres clients
      • écriture de la requête
      • déverrouillage
      • fermeture du fifo
    • lancement du deuxième client: (en boucle)
      • ouverture du fifo en écriture
      • verrouillage de l'écriture pour les autres clients
      • écriture de la requête
      • déverrouillage
      • fermeture du fifo
    • Quitte client 1
    • Quitte client 2
    • Kill du serveur manuellement par la suite

  16. #16
    Membre émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut
    Pour reprendre ce que dit souviron, si je traduit :

    EBADF fd is not an open file descriptor, or the command was F_SETLK or F_SETLKW and the file descriptor open mode doesn’t match with the type of lock requested.
    En Français, cela donne :

    EBADF fd n'est pas un descripteur de fichier ouvert, ou la commande est F_SETLK ou F_SETLKW et le mode d'ouverture du descripteur ne correspond pas au type de verouillage demandé.
    Autrement dit, ton fnctl plante car il manque un flag dans ton open ! CQFD.

  17. #17
    Membre éclairé
    Homme Profil pro
    Analyste/développeur Java EE
    Inscrit en
    Janvier 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste/développeur Java EE

    Informations forums :
    Inscription : Janvier 2005
    Messages : 376
    Par défaut
    C'est bon, j'ai trouvé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
       // Ouverture du fifo pour la requête
        fdW = open("/tmp/requete", O_WRONLY);
        if (fdW == -1) {
          perror("Erreur d'ouverture du fichier serveur");
          return -1;
        }
     
        //Verrouillage
        verrou.l_type = F_WRLCK;
        verrou.l_whence = SEEK_SET;
        verrou.l_start = 0;
        verrou.l_len = 0;
     
        if (fcntl(fdW, F_SETLK, &verrou)== -1){
          perror("Erreur de verrouillage");
          return -1;
        }
     
        //Envoi de la requete
        nbWrite = write(fdW, &requete, sizeof(requete));
        if (nbWrite < sizeof(requete)) {
          perror("Erreur d'écriture");
          return -1;
        }
     
        //Déverrouillage
        verrou.l_type = F_UNLCK; 
        if (fcntl(fdW, F_SETLKW, &verrou)== -1){
          perror("Erreur de deverrouillage");
          return -1;
        }
     
        close(fdW);
    Ce qui était mauvais, c'est ceci: (ancien code)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        //Verrouillage
        verrou.l_type = F_RDLCK; //bloque l'écriture aux autres processus (donc autres clients)
        verrou.l_whence = 0;
        verrou.l_start = 0;
        verrou.l_len = 0;
     
        if (fcntl(fdW, F_SETLKW, &verrou)== -1){
          perror("Erreur de verrouillage");
        }
    Merci à vous pour votre aide

  18. #18
    Membre émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut
    N'oublie pas de flager le post avec le bouton !

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

Discussions similaires

  1. Application accessible par plusieurs utilisateurs en même temps..
    Par flamby6969 dans le forum Modélisation
    Réponses: 3
    Dernier message: 30/03/2009, 01h42
  2. Ouvrire access par plusieur utilisateurs
    Par sid_ali_2007 dans le forum IHM
    Réponses: 1
    Dernier message: 08/03/2008, 20h41
  3. Réponses: 6
    Dernier message: 16/07/2007, 17h44
  4. Réponses: 22
    Dernier message: 24/11/2006, 00h42
  5. Variable accessible par plusieurs clients
    Par mezoo dans le forum Servlets/JSP
    Réponses: 3
    Dernier message: 06/10/2006, 11h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo