2010-02-21 4 views
1

pré-fork Unix Network Programming, il est un exemple d'un serveur pré-fourchue qui utilise le passage de messages sur un Unix tube de domaine pour instruire les processus enfants pour gérer une connexion entrante:Partage des descripteurs de fichiers entre parents et enfants

for (; ;) { 
    rset = masterset; 
    if (navail <= 0) 
     FD_CLR(listenfd, &rset); /* turn off if no available children */ 
    nsel = Select(maxfd + 1, &rset, NULL, NULL, NULL); 

     /* 4check for new connections */ 
    if (FD_ISSET(listenfd, &rset)) { 
     clilen = addrlen; 
     connfd = Accept(listenfd, cliaddr, &clilen); 

     for (i = 0; i < nchildren; i++) 
      if (cptr[i].child_status == 0) 
       break;    /* available */ 

     if (i == nchildren) 
      err_quit("no available children"); 
     cptr[i].child_status = 1; /* mark child as busy */ 
     cptr[i].child_count++; 
     navail--; 

     n = Write_fd(cptr[i].child_pipefd, "", 1, connfd); 
     Close(connfd); 
     if (--nsel == 0) 
      continue; /* all done with select() results */ 
} 

Comme vous pouvez le voir, le parent écrit le numéro de descripteur de fichier pour le socket sur le canal, puis appelle le close sur le descripteur de fichier. Lorsque les enfants préformés finissent avec le socket, ils appellent aussi le descripteur. La chose qui me lance pour une boucle est que parce que ces enfants sont préformés, je suppose que seuls les descripteurs de fichiers qui existaient au moment où les enfants étaient fourchus seraient partagés. Cependant, si cela était vrai, alors cet exemple échouerait spectaculairement, mais cela fonctionne.

Quelqu'un peut-il faire la lumière sur la façon dont les descripteurs de fichiers créés par le parent après la branche finissent par être partagés avec le processus enfants?

Répondre

5

Jetez un coup d'œil à l'implémentation de Write_fd. Il utilise quelque chose comme

union { 
    struct cmsghdr  cm; 
    char       control[CMSG_SPACE(sizeof(int))]; 
} control_un; 
struct cmsghdr *cmptr; 

msg.msg_control = control_un.control; 
msg.msg_controllen = sizeof(control_un.control); 

cmptr = CMSG_FIRSTHDR(&msg); 
cmptr->cmsg_len = CMSG_LEN(sizeof(int)); 
cmptr->cmsg_level = SOL_SOCKET; 
cmptr->cmsg_type = SCM_RIGHTS; 
*((int *) CMSG_DATA(cmptr)) = sendfd; 

C'est, l'envoi d'un message de contrôle avec SCM_RIGHTS type est une façon unix peut partager un descripteur de fichier avec un processus unreleated.

1

Vous pouvez envoyer (la plupart) des descripteurs de fichiers arbitraires à un processus potentiellement indépendant en utilisant le mécanisme de transmission FD dans les sockets Unix.

Ceci est typiquement un mécanisme peu utilisé et plutôt difficile à obtenir correctement - les deux processus doivent coopérer.

La plupart des serveurs prefork ne font PAS cela, mais ils ont l'appel de processus enfant accept() sur un socket d'écoute partagé, et créent leur propre socket connectée de cette façon. Les autres processus ne peuvent pas voir cette socket connectée, et il n'y en a qu'une seule copie, donc quand l'enfant la ferme, c'est parti. Un inconvénient est que le processus ne peut pas dire ce que le client va demander AVANT d'appeler accepter, donc vous ne pouvez pas gérer différents types de demandes dans différents enfants etc. Une fois qu'un enfant l'a accepté, un autre enfant ne peut pas.

+0

Oui, je ne peux pas vraiment voir beaucoup de raisons d'utiliser un serveur pré-fourchu à tous ces jours; Je choisirais à peu près toujours un serveur pré-threadé. Le seul cas où je pourrais lancer un serveur pré-fourchu serait peut-être pour des raisons de sécurité où vous voulez isoler chaque espace mémoire de tous les autres clients afin que le piratage ou la génération d'une erreur dans un client ne supprime pas le système entier ou exposer des données utilisateur sensibles. –

+0

Les serveurs préforgés sont bons car ils empêchent les fuites de mémoire de casser des choses. Les processus enfants peuvent quitter et être recyclés sans interrompre le service, en récupérant la mémoire. Les serveurs fourchus – MarkR

+0

vous protègent également 3. des éléments de partie qui ne sont pas sécurisés par les threads, et supposent qu'il n'y a qu'un seul thread d'exécution. Il y a beaucoup de ces bibliothèques autour. – nos

Questions connexes