linux fork: empêche l’inheritance des descripteurs de fichiers

Comment empêche-t-on un descripteur de fichier d’être hérité de la copie sur les appels système fork () sans le fermer, bien sûr?

Je cherche un moyen de marquer un seul descripteur de fichier comme N’EST PAS (copy-) hérité par des enfants à fork (), quelque chose comme un hack FD_CLOEXEC-like mais pour des forks (donc une fonctionnalité FD_DONTINHERIT si vous voulez). Quelqu’un a fait ça? Ou regardé cela et a un indice pour moi de commencer?

Je vous remercie

METTRE À JOUR:

Je pourrais utiliser la libreg’s __register_atfork

__register_atfork(NULL, NULL, fdcleaner, NULL) 

fermer le fds dans child juste avant que fork () ne retourne. Cependant, les fds sont toujours en cours de copie, donc cela me semble être un bidouillage idiot. La question est de savoir comment ignorer le dup () – en utilisant l’enfant de fds inutiles

Je pense à certains scénarios où un fcntl (fd, F_SETFL, F_DONTINHERIT) serait nécessaire:

  • fork () copiera un événement fd (par exemple epoll); Parfois, cela n’est pas souhaité, par exemple, FreeBSD marque l’événement kqueue () fd comme étant de type KQUEUE_TYPE et ces types de fds ne seront pas copiés sur tous les forks (les fichiers fs de kqueue sont ignorés de la copie, si l’on veut l’utiliser à partir d’un enfant qu’il doit bifurquer avec la table partagée fd)

  • fork () copiera 100k fd inutiles pour bricoler un enfant pour effectuer des tâches cpu (supposons que le besoin d’un fork () soit très faible et que le programmeur ne veuille pas conserver un pool d’enfants pour quelque chose qui ne le serait normalement pas) t arrive)

Certains descripteurs que nous voulons être copiés (0,1,2), certains (la plupart d’entre eux?) Non. Je pense que le dupable complet est là pour des raisons historiques, mais je me trompe probablement.

Comment bête ça sonne:

  • patch fcntl pour prendre en charge l’indicateur dontinherit sur les descripteurs de fichiers (pas sûr que l’indicateur soit conservé par -fd ou dans un fdtable fd_set, comme les indicateurs de fermeture-sur-exécution sont conservés
  • modifier dup_fd () dans le kernel pour ignorer la copie de fds dontinherit , comme le fait freebsd pour les kq fds

considérer le programme

 #include  #include  #include  #include  #include  #include  static int fds[NUMFDS]; clock_t t1; static void cleanup(int i) { while(i-- >= 0) close(fds[i]); } void clk_start(void) { t1 = clock(); } void clk_end(void) { double tix = (double)clock() - t1; double sex = tix/CLOCKS_PER_SEC; printf("fork_cost(%d fds)=%fticks(%f seconds)\n", NUMFDS,tix,sex); } int main(int argc, char **argv) { pid_t pid; int i; __register_atfork(clk_start,clk_end,NULL,NULL); for (i = 0; i < NUMFDS; i++) { fds[i] = open("/dev/null",O_RDONLY); if (fds[i] == -1) { cleanup(i); errx(EXIT_FAILURE,"open_fds:"); } } t1 = clock(); pid = fork(); if (pid < 0) { errx(EXIT_FAILURE,"fork:"); } if (pid == 0) { cleanup(NUMFDS); exit(0); } else { wait(&i); cleanup(NUMFDS); } exit(0); return 0; } 

bien sûr, ne peut pas considérer cela comme un vrai banc mais de toute façon:

 root@pinkpony:/home/cia/dev/kqueue# time ./forkit fork_cost(100 fds)=0.000000ticks(0.000000 seconds) real 0m0.004s user 0m0.000s sys 0m0.000s root@pinkpony:/home/cia/dev/kqueue# gcc -DNUMFDS=100000 -o forkit forkit.c root@pinkpony:/home/cia/dev/kqueue# time ./forkit fork_cost(100000 fds)=10000.000000ticks(0.010000 seconds) real 0m0.287s user 0m0.010s sys 0m0.240s root@pinkpony:/home/cia/dev/kqueue# gcc -DNUMFDS=100 -o forkit forkit.c root@pinkpony:/home/cia/dev/kqueue# time ./forkit fork_cost(100 fds)=0.000000ticks(0.000000 seconds) real 0m0.004s user 0m0.000s sys 0m0.000s 

forkit a fonctionné sur un Dell Inspiron 1520 Intel (R) Core (TM) 2 Duo CPU T7500 à 2,20 GHz avec 4 Go de RAM; average_load = 0.00

Non. Fermez-les vous-même, car vous savez lesquels doivent être fermés.

Si vous lancez un appel pour appeler une fonction exec , vous pouvez utiliser fcntl avec FD_CLOEXEC pour que le descripteur de fichier soit fermé une fois que vous avez exec :

 int fd = open(...); fcntl(fd, F_SETFD, FD_CLOEXEC); 

Un tel descripteur de fichier survivra à un fork mais pas aux fonctions de la famille exec .

Il n’existe pas de méthode standard à ma connaissance.

Si vous voulez l’implémenter correctement, la meilleure façon de le faire est probablement d’append un appel système pour marquer le descripteur de fichier comme étant proche de la fourche et d’intercepter l’ sys_fork système sys_fork (syscall number 2) pour qu’il agisse. sur ces drapeaux après avoir appelé le sys_fork origine.

Si vous ne voulez pas append un nouvel appel système, vous pouvez peut-être intercepter sys_ioctl (syscall number 54) et simplement lui append une nouvelle commande pour marquer une description de fichier close-on-fork.

Bien sûr, si vous pouvez contrôler ce que fait votre application, il peut être préférable de conserver des tables de niveau utilisateur de tous les descripteurs de fichiers que vous souhaitez fermer sur Fourche et d’appeler votre propre myfork place. Cela ferait une fourchette, puis passerait par la table de niveau utilisateur fermant les descripteurs de fichiers ainsi marqués.

Vous n’auriez alors pas à manipuler le kernel Linux, une solution qui n’est probablement nécessaire que si vous n’avez pas le contrôle du processus fork (si une bibliothèque tierce fait des appels fork() ).