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

 C Discussion :

Partage d'ouverture de fichier entre processus


Sujet :

C

  1. #1
    Membre habitué Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Points : 196
    Points
    196
    Par défaut Partage d'ouverture de fichier entre processus
    Bonsoir,
    j'ai un petit soucis. J'ai un processus principal qui crée différents fils. Dans un des fils, ce dernier ouvre différentes sockets. Je voudrai ouvrir et pouvoir utiliser ses sockets dans un autre processus fils (donc entre eux, ils sont simplement frère, et non père et fils). Le fils qui créent les différentes sockets (en mode connecté - à chaque nouvelle connexion d'un client) ne sait pas à l'avance combien il y en aura. Est-ce qu'un tableau de socket mis à jour en global (mmap()) pourrait faire l'affaire? Je ne sais pas trop utiliser ce genre de fonctions, et je ne les comprends pas encore très bien.
    J'aimerai simplement savoir quelle direction prendre, car là je bloque un peu. Je cherche, mais je n'ai pas l'impression de trouver ce qu'il me faut.
    Merci d'avance.

    edit : et si le fils voulant ouvrir les sockets ouvert de l'autre ne faisait que d'ouvrir le fichier comme http://www.lainoox.com/bash-socket-programming/ ?
    Car de toute façon ce dernier, ne veut qu'envoyer des données et non les lire. Mais est-ce que le client recevra bien le message, je n'ai pas encore essayé...
    "Les spécialistes commencent par n'apprendre que ce qu'ils aiment et finissent par n'aimer que ce qu'ils ont appris." - Gilbert Cesbron
    "Si nous avons chacun un objet et que nous les echangeons, nous avons chacun un objet. Si nous avons chacun une idée et que nous les échangeons, nous avons chacun deux idées." - Proverbe Chinois.

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Je présume que t'es sous Unix/Linux et que tes fils sont créés par fork() et non thread(). Dans ce cas, il y a indépendance totale des processus entre eux. Ce qui est créé dans le processus X n'est accessible que dans le processus X. Ils sont aussi accesibles dans ses propres fils éventuels mais uniquement en tant que "copie". Si par exemple t'as une variable "a" qui vaut 10 et que tu crées un fils, celui-ci aura alors une variable "a" personnelle qui vaudra aussi 10 mais copiée depuis son père et indépendante de cette dernière. Si dans le fils tu mets a à 15, celle du père restera à 10.

    En ce qui concerne les fichiers/socket, c'est un petit peu différent. En effet, un fichier/socket que tu gères dans ton programme n'est qu'un lien vers un "truc" géré par le noyau. Et c'est un lien numérique. Donc (exemple) si tu ouvres ton fichier dans le père et que tu stockes son adresse dans un FILE *fp puis que tu crées un fils, celui-ci aura alors une copie de "fp" et cette copie pointera vers le même élément système. Donc si le père écrit dans fp et que le fils écrit lui-aussi, les deux écritures se feront alors sur le vrai fichier disque (avec des collisions sans nom si ces écritures se font à la porcasse sans gestion).

    A partir de là, je vois deux possibilités
    1. tu ouvres ta socket dans le père. Tous les fils y auront alors accès
    2. tu ouvres ta socket dans le processus fils F1 puis tu transmets son identificateur à F2 via les outils de transmission d'information. En vrac il y a socket (ben oui, tu peux très bien utiliser pour ça une autre socket latérale ouverte dans le père), mémoire partagée, pipe, file de messages.


    Perso je pencherais pour la première solution. C'est beaucoup plus simple à mettre en oeuvre. C'est d'ailleurs ainsi que fonctionnent les serveurs. Ils ouvrent une socket puis écoutent et dès qu'une connection arrive, ils créent un fils et laissent le fils se dépatouiller avec le client...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Membre habitué Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Points : 196
    Points
    196
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Bonjour

    Je présume que t'es sous Unix/Linux et que tes fils sont créés par fork() et non thread(). Dans ce cas, il y a indépendance totale des processus entre eux. Ce qui est créé dans le processus X n'est accessible que dans le processus X. Ils sont aussi accesibles dans ses propres fils éventuels mais uniquement en tant que "copie". Si par exemple t'as une variable "a" qui vaut 10 et que tu crées un fils, celui-ci aura alors une variable "a" personnelle qui vaudra aussi 10 mais copiée depuis son père et indépendante de cette dernière. Si dans le fils tu mets a à 15, celle du père restera à 10.
    Oui je suis exclusivement sur un système Unix/Linux. Oui en effet, je n'ai pas précisé, mais le fils en question est créé à partir de fork et non thread.
    Merci pour les précisions, tout cela me semblait bien clair.

    Citation Envoyé par Sve@r Voir le message
    En ce qui concerne les fichiers/socket, c'est un petit peu différent. En effet, un fichier/socket que tu gères dans ton programme n'est qu'un lien vers un "truc" géré par le noyau. Et c'est un lien numérique. Donc (exemple) si tu ouvres ton fichier dans le père et que tu stockes son adresse dans un FILE *fp puis que tu crées un fils, celui-ci aura alors une copie de "fp" et cette copie pointera vers le même élément système. Donc si le père écrit dans fp et que le fils écrit lui-aussi, les deux écritures se feront alors sur le vrai fichier disque (avec des collisions sans nom si ces écritures se font à la porcasse sans gestion).

    A partir de là, je vois deux possibilités
    1. tu ouvres ta socket dans le père. Tous les fils y auront alors accès
    2. tu ouvres ta socket dans le processus fils F1 puis tu transmets son identificateur à F2 via les outils de transmission d'information. En vrac il y a socket (ben oui, tu peux très bien utiliser pour ça une autre socket latérale ouverte dans le père), mémoire partagée, pipe, file de messages.


    Perso je pencherais pour la première solution. C'est beaucoup plus simple à mettre en oeuvre. C'est d'ailleurs ainsi que fonctionnent les serveurs. Ils ouvrent une socket puis écoutent et dès qu'une connection arrive, ils créent un fils et laissent le fils se dépatouiller avec le client...
    [/quote]
    C'est ce que j'ai fais, j'utilise une Fifo (vachement pratique) pour la communication entre ces deux fils. Sauf que l'écriture récupérant bien le numéro du fichier (de la Socket) ne semble pas marcher (write par exemple me retourne bien -1 : pourtant du côté de l'autre côté tout marche nickel.
    La valeur de la socket_fd vaut 4 (normal, c'est dans l'ordre) pour le client1, et le client2 se connecte (donc nouveau fils) avec comme valeur 5. Pour ce qui est du fils qui veut récupérer la valeur socket_fd et écrire dans la socket (1er fils créé - par ailleurs) n'y arrive pas - comme dit ci-dessus write me retourne -1.
    Errno m'indique que "Bad file descriptor" par strerror (code 9).

    edit : en exécutant mon programme, et en regardant dans /proc/<PID proc>/fd/ je vois bien apparaître la liste des fichiers ouvert, dont les sockets. Ne pourrais-je pas récupérer l'id du processus ouvrant les sockets, et dans l'autre processus ouvrir le fichier /proc/<PID pro>/fd/x (étant donné que le fd du processus est correctement passé par Fifo) pour ainsi y écrire et la fermer aussitôt.
    Je comprends bien un peu mieux comment marche les processus sur Unix. C'est vachement bien foutu au final ><'', et je comprends bien pourquoi Bad file descriptor pour le processus qui essaie d'utiliser la socket.
    "Les spécialistes commencent par n'apprendre que ce qu'ils aiment et finissent par n'aimer que ce qu'ils ont appris." - Gilbert Cesbron
    "Si nous avons chacun un objet et que nous les echangeons, nous avons chacun un objet. Si nous avons chacun une idée et que nous les échangeons, nous avons chacun deux idées." - Proverbe Chinois.

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par dafpp Voir le message
    C'est ce que j'ai fais, j'utilise une Fifo (vachement pratique) pour la communication entre ces deux fils. Sauf que l'écriture récupérant bien le numéro du fichier (de la Socket) ne semble pas marcher (write par exemple me retourne bien -1 : pourtant du côté de l'autre côté tout marche nickel.
    C'est un peu ce que je craignais quand j'ai écrit mon post précédent.

    Voici un petit exemple qui, je pense, illustre ton idée (sauf que je transmets un FILE* et non une socket)

    Code c : 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
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    #include <stdio.h>
    #include <stdlib.h>
     
    int main()
    {
    	int tube[2];
    	int f1;
    	int f2;
    	pipe(tube);
     
    	if (fork() == 0)
    	{
    		fils1(tube);
    		exit(0);
    	}
    	if (fork() == 0)
    	{
    		fils2(tube);
    		exit(0);
    	}
     
    	wait(&f1);
    	wait(&f2);
    	printf("père terminé - f1=%d, f2=%d\n", f1, f2);
    }
     
    int fils1(int tube[2])
    {
    	FILE *fp;
     
    	close(tube[0]);
    	fp=fopen("/etc/passwd", "r");
    	printf("Fils1: fp=%p\n", fp);
    	write(tube[1], &fp, sizeof(FILE*));
    }
     
    int fils2(int tube[2])
    {
    	FILE *fp;
    	char ligne[80];
     
    	close(tube[1]);
    	read(tube[0], &fp, sizeof(FILE*));
    	printf("Fils2: fp=%p\n", fp);
    	if (fgets(ligne, 80, fp) == NULL)
    		perror("fgets");
    	printf("ligne=%s", ligne);
    	fclose(fp);
    }

    Ca devrait fonctionner, le pointeur récupéré dans f2 a bien la même valeur que celui passé dans f1... mais ça ne fonctionne pas.

    Je pense que l'opération fopen() va créer des liens entre le processus et le fichier et que ces liens sont écrits dans le FILE*. Par exemple on pourrait imaginer que le FILE* contient un champ "pid" et donc que seul le processus ayant instancié le fopen() a le droit d'accéder dans ce FILE* (ce n'est pas le cas bien entendu car un fils qui hériterait de ce FILE* aurait lui-aussi le droit d'y accéder mais c'est juste pour illustrer le problème). Donc même en transmettant la bonne valeur du FILE* à un autre processus distinct (ici f2) ben ça ne peut pas fonctionner (le noyau Unix n'a pas de liens connus entre f2 et le fichier en question). Et ça le peut tellement pas que même fgets() ne renvoie pas NULL (je n'ai même pas de perror()). Et c'est sûrement pareil avec ta socket.

    Donc seule solution que je vois: le père ouvre la socket et tous les fils frères pourront y accéder. A la limite au lieu d'ouvrir ta socket dans F1 et essayer de la transmettre à son frère F2 tu l'ouvres dans F1 puis de là tu crées deux fils F11 et F12 qui auront tous deux accès à la socket...

    PS: Autre exemple écrit à partir du premier qui illustre bien la possibilité à un fils d'accéder à un FILE* ouvert dans le père

    Code c : 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
    #include <stdio.h>
    #include <stdlib.h>
     
    int main()
    {
    	int f;
    	FILE *fp;
    	fp=fopen("/etc/passwd", "r");
     
    	if (fork() == 0)
    	{
    		fils(fp);
    		fclose(fp);
    		exit(0);
    	}
     
    	wait(&f);
    	fclose(fp);
    	printf("père terminé - f=%d\n", f);
    }
     
    int fils(FILE *fp)
    {
    	char ligne[80];
     
    	printf("Fils: fp=%p\n", fp);
    	if (fgets(ligne, 80, fp) == NULL)
    		perror("fgets");
    	printf("ligne=%s", ligne);
    }
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Membre habitué Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Points : 196
    Points
    196
    Par défaut
    Désolé pour la réponse tardive. Si ça marche c'est super. Je n'ai pas la possibilité d'essayer ce soir. Je reposterai demain à l'occasion pour confirmer tout ça.
    Merci à toi
    "Les spécialistes commencent par n'apprendre que ce qu'ils aiment et finissent par n'aimer que ce qu'ils ont appris." - Gilbert Cesbron
    "Si nous avons chacun un objet et que nous les echangeons, nous avons chacun un objet. Si nous avons chacun une idée et que nous les échangeons, nous avons chacun deux idées." - Proverbe Chinois.

  6. #6
    Membre habitué Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Points : 196
    Points
    196
    Par défaut
    Malheureusement, ça ne marche pas avec les sockets. Sur Gnu, les fichiers ouverts (peut-être que FILE * est à part) sont propre au processus. Et vu que je récupère le fd de la socket (par ex 4), et que que ce dernier n'a jamais été ouvert par le proc (/proc/<pid>/fd/) alors dans ce cas je me retrouve toujours avec le problème de Bad file descriptorr. Avec une fifo je faisais déjà le travail du tube, et je me heurtais au même problème. Je pensais que vu qu'avec le tube on passait un pointeur (donc une adresse), ça aurait pû marcher. Mais passer une adresse par un tube ne résoudra encore moins le problème car les processus ne partagent pas le même espace mémoire (fork()). Avec ton exemple (FILE *) je pensais que c'était le cas mais non. Les FILE * doivent être géré autrement sans doute qu'un simple open. (ou pas?).
    Bon je reste bloqué. Je pense que la meilleure solution c'est de repenser le code pour que celui qui crée les sockets soient celui qui puissent les ouvrir aussi... Ça sera plus simple.

    edit : j'avais mal lu ton message, donc effet, toi même tu le disais que ça n'a allait pas marché. Et tu n'avais pas tort
    "Les spécialistes commencent par n'apprendre que ce qu'ils aiment et finissent par n'aimer que ce qu'ils ont appris." - Gilbert Cesbron
    "Si nous avons chacun un objet et que nous les echangeons, nous avons chacun un objet. Si nous avons chacun une idée et que nous les échangeons, nous avons chacun deux idées." - Proverbe Chinois.

Discussions similaires

  1. Partage d'une liste chainée entre Processus
    Par la_chevre dans le forum Débuter
    Réponses: 7
    Dernier message: 09/10/2008, 12h35
  2. Partage des fichiers entre projets Eclipse
    Par laura_cornel dans le forum Eclipse Java
    Réponses: 9
    Dernier message: 11/12/2006, 11h52
  3. relation entre fichier et processus
    Par ouadie99 dans le forum Delphi
    Réponses: 1
    Dernier message: 16/08/2006, 21h11
  4. [win] problème pour partager des fichiers entre 2 pc
    Par goma771 dans le forum Administration
    Réponses: 1
    Dernier message: 01/12/2005, 16h15
  5. Partage de fichier entre Linux et Mac
    Par maddog2032 dans le forum Réseau
    Réponses: 3
    Dernier message: 14/04/2005, 08h32

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