web-dev-qa-db-fra.com

Comment vérifier si un descripteur de fichier donné stocké dans une variable est toujours valide?

J'ai un descripteur de fichier stocké dans une variable disons var. Comment puis-je vérifier si ce descripteur est valide à un stade ultérieur?

  fdvar1= open(.....);
  fdvar2 = fdvar1;       // Please ignore the bad design

  ....
  // lots of loops , conditionals and threads. It can call close(fdvar2) also.  
  ....

  if(CheckValid(fdvar1)) // How can I do this check  ?
    write(fdvar1, ....);

Maintenant, je veux vérifier si var1 (qui contient toujours le descripteur ouvert) est toujours valide. Des API pour ça?

43
Lunar Mushrooms

fcntl(fd, F_GETFD) est le moyen le moins cher canonique de vérifier que fd est un descripteur de fichier ouvert valide. Si vous devez beaucoup vérifier par lots, utilisez poll avec un délai d'expiration nul et le membre events mis à 0 et vérifiez POLLNVAL dans revents après il revient est plus efficace.

Cela dit, l'opération "vérifier si un descripteur de ressource donné est toujours valide" est presque toujours fondamentalement incorrecte. Une fois qu'un descripteur de ressource est libéré (par exemple, un fd est closed), sa valeur peut être réaffectée à la prochaine ressource que vous allouez. S'il reste des références qui pourraient être utilisées, elles fonctionneront à tort sur la nouvelle ressource plutôt que sur l'ancienne. Ainsi, la vraie réponse est probablement: si vous ne connaissez pas déjà la logique de votre programme, vous avez des erreurs logiques fondamentales majeures qui doivent être corrigées.

73
R..

Vous pouvez utiliser la fonction fcntl():

int fd_is_valid(int fd)
{
    return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
}
23
user529758

Je ne pense pas qu'il existe une fonction qui puisse vous dire si le descripteur est toujours valide. Le descripteur est généralement juste un petit entier comme 6 et votre libc peut choisir de réutiliser ce nombre si vous fermez le fichier et en ouvrez un nouveau plus tard.

Au lieu de cela, vous devriez envisager d'utiliser dup() pour copier le descripteur de fichier. En dupliquant le descripteur de fichier au lieu d'utiliser le même descripteur à plusieurs endroits, il peut devenir plus facile pour vous de savoir si le descripteur de fichier est toujours valide. Vous devez juste vous rappeler de fermer à la fois le descripteur d'origine et le descripteur en double lorsque vous avez terminé.

5
David Grayson

De this article du forum:

int is_valid_fd(int fd)
{
    return fcntl(fd, F_GETFL) != -1 || errno != EBADF;
}

fcntl (GETFL) est probablement l'opération la moins chère et la moins susceptible d'échouer que vous pouvez effectuer sur un descripteur de fichier. En particulier, la spécification suggère qu'elle ne peut pas être interrompue par des signaux et qu'elle n'est affectée par aucune sorte de verrou maintenu n'importe où.

4
wbao

Il me semble que si vous voulez savoir si elle pointe toujours vers la même ressource, une approche (non parfaite) serait de fstat() le descripteur juste après l'ouverture et ensuite vous pouvez le faire à nouveau et comparer les résultats. Commencez par regarder .st_mode & S_IFMT Et continuez - est-ce un objet de système de fichiers? Regardez .st_dev / .st_ino. Est-ce une prise? Essayez getsockname(), getpeername(). Ce ne sera pas certain à 100%, mais il peut vous dire si ce n'est certainement pas la même chose.

0
John Hascall