L'obtention de la plus haute attribuée descripteur de fichier
Est là de façon portable (POSIX) pour obtenir la plus haute attribuée descripteur de fichier numéro du processus en cours?
Je sais qu'il y a une belle manière de faire le nombre sur AIX, par exemple, mais je suis à la recherche d'un portable de la méthode.
La raison pour laquelle je te demande, c'est que je veux fermer tous les descripteurs de fichiers ouverts. Mon programme est un serveur qui s'exécute en tant que root et les fourches et les execs enfant de programmes pour les utilisateurs non-root. Laissant le privilège des descripteurs de fichiers ouverts dans le processus de l'enfant est un problème de sécurité. Certains descripteurs de fichier peut être ouvert que par le code je ne peux pas le contrôle (la bibliothèque C, des bibliothèques tierces, etc.), je ne peux donc pas compter sur FD_CLOEXEC
soit.
- Notez qu'il serait préférable de simplement ouvrir tous vos fichiers avec le close-on-exec indicateur est défini de sorte qu'ils sont automatiquement fermé par un de la
exec
-les fonctions de la famille. - Moderne glibc prend en charge le "e" stdio.h FICHIER* indicateur d'ouverture de caractères pour indiquer FD_CLOEXEC traitement.
- Également intéressant de noter que close-on-exec n'est pas close-sur-fourche. Si vous avez une fourche non privilégié processus enfant pour exécuter un sous-programme à partir du même programme, le processus enfant d'hériter les descripteurs de fichier de l'privilégié des parents. Il n'est pas trivial de rappeler à proximité de tous ceux que vous n'avez pas besoin. Close-on-exec n'aide pas dans cette situation.
Vous devez vous connecter pour publier un commentaire.
Tout portable, la fermeture de tous les descripteurs de fichier jusqu'à
sysconf(_SC_OPEN_MAX)
n'est pas fiable, parce que sur la plupart des systèmes de cet appel renvoie le descripteur de fichier de la limite douce, qui aurait pu être abaissée en dessous de la plus haute utilisés descripteur de fichier. Un autre problème est que sur de nombreux systèmessysconf(_SC_OPEN_MAX)
peut retournerINT_MAX
, ce qui peut provoquer cette approche trop lent. Malheureusement, il n'est pas fiable, portable alternative qui ne nécessite pas de parcourir tous les cas éventuels de non-négatif int descripteur de fichier.Mais pas portable, la plupart des systèmes d'exploitation en usage courant aujourd'hui de fournir une ou plusieurs des solutions suivantes pour résoudre ce problème:
Une fonction de bibliothèque à fermer tous les descripteurs de fichier >= fd. C'est la solution la plus simple pour le cas de la fermeture de tous les descripteurs de fichier, bien qu'il ne peut pas être utilisé pour beaucoup de choses. Pour fermer tous les descripteurs de fichier, sauf pour un certain ensemble,
dup2
peut être utilisé pour déplacer vers le bas de la fourchette à l'avance, et de les replacer par la suite si nécessaire.closefrom(fd)
(Solaris 9 ou plus tard, FreeBSD 8.0 7.3 ou et plus tard, NetBSD 3.0 ou plus tard, à partir de la version 3.5 ou ultérieure.)fcntl(fd, F_CLOSEM, 0)
(AIX, IRIX, NetBSD)Une fonction de la bibliothèque pour fournir la maximum de descripteurs de fichiers actuellement utilisée par le processus. Pour fermer tous les descripteurs de fichier ci-dessus un certain nombre, soit près tous d'entre eux jusqu'à ce maximum, ou obtenez en permanence et à proximité de la plus haute descripteur de fichier dans une boucle jusqu'à ce que le faible lié est atteint. Ce qui est plus efficace repose sur le descripteur de fichier de la densité.
fcntl(0, F_MAXFD)
(NetBSD)pstat_getproc(&ps, sizeof(struct pst_status), (size_t)0, (int)getpid())
Renvoie des informations sur le processus, y compris la plus haute descripteur de fichier ouvert dans
ps.pst_highestfd
. (HP-UX)Une fonction de bibliothèque à liste de tous les descripteurs de fichier actuellement utilisée par le processus. C'est plus souple en ce qu'elle permet de fermer tous les descripteurs de fichiers, la recherche de la plus haute descripteur de fichier, ou de faire à peu près rien d'autre sur chaque descripteur de fichier ouvert, peut-être même ceux d'un autre processus. Exemple (OpenSSH)
proc_pidinfo(getpid(), PROC_PIDLISTFDS, 0, fdinfo_buf, sz)
(macOS)Un répertoire contenant une entrée pour chaque descripteur de fichier ouvert. Ceci est similaire à la ci-dessus, sauf que ce n'est pas une fonction de la bibliothèque. Cela peut être plus compliqué que les autres approches pour les utilisations courantes, et peuvent échouer pour une variété de raisons telles que la proc/fdescfs pas monté, un environnement chroot, ou pas de descripteurs de fichiers disponibles pour ouvrir le répertoire (processus ou d'un système de limite). Par conséquent, l'utilisation de cette approche est souvent combiné avec un mécanisme de secours. Exemple (OpenSSH), un autre exemple (glib).
/proc/
pid/fd/
ou/proc/self/fd/
(Linux, Solaris, AIX, Cygwin, NetBSD)(AIX ne prend pas en charge "
self
")/dev/fd/
(FreeBSD, macOS)Il peut être difficile de gérer tous les cas de coin de manière fiable avec cette approche. Par exemple, considérons la situation où tous les descripteurs de fichier >= fd sont fermées, mais tous les descripteurs de fichier < fd sont utilisés, le processus actuel plafond de ressources est fd, et il y a des descripteurs de fichier >= fd en cours d'utilisation. Parce que le processus de plafond de ressources a été atteint, le répertoire ne peut pas être ouvert. Si la fermeture de chaque descripteur de fichier de fd à travers le plafond de ressources ou
sysconf(_SC_OPEN_MAX)
est utilisé comme un secours, rien ne sera fermé.POSIX façon est:
(à noter que la fermeture de 3, pour garder stdin/stdout/stderr ouvert)
close() sans danger retourne EBADF si le descripteur de fichier n'est pas ouvert. Il n'y a pas besoin de gaspiller un autre système d'appel de vérification.
Certains systèmes Unix support un closefrom(). Cela évite le trop grand nombre d'appels à close() selon le maximum possible descripteur de fichier nombre. Alors que la meilleure solution, je suis conscient de, c'est complètement non-compatibles.
J'ai écrit du code pour gérer tous une plateforme spécifique. Toutes les fonctions sont asynchrones signal fort. Pensais que les gens pourraient trouver cela utile. Testé uniquement sur OS X dès maintenant, n'hésitez pas à améliorer/corriger.
Droit lorsque votre programme a commencé et n'a pas ouvert de quoi que ce soit. E. g. comme le début de main(). tuyau de la fourche et commencer immédiatement un exécuteur serveur. Cette façon qu'elle a de la mémoire et d'autres détails est propre et vous pouvez juste lui donner des choses à fourche & exec.
Si vous voulez faire des IO sur le programme exécuté l'exécuteur serveur devra faire socket redirections et vous pouvez utiliser les sockets unix.
Pourquoi ne pas vous fermer tous les descripteurs de 0 à, disons, 10000.
Il serait assez rapide, et la pire chose qui pourrait arriver est EBADF.