58

我有一个文件描述符存储在变量 var 中。如何在以后检查该描述符是否有效?

  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, ....);

现在我想检查 var1 (仍然保存打开的描述符)是否仍然有效。有任何 API 吗?

4

6 回答 6

89

fcntl(fd, F_GETFD)是检查是否fd是有效的打开文件描述符的规范最便宜的方法。如果您需要批量检查很多,使用poll零超时并将events成员设置为 0 并POLLNVALrevents返回后检查更有效。

话虽如此,“检查给定资源句柄是否仍然有效”的操作几乎总是从根本上不正确。释放资源句柄后(例如,fd 是closed),它的值可能会重新分配给您分配的下一个此类资源。如果有任何剩余的引用可能被使用,它们将错误地对新资源而不是旧资源进行操作。因此,真正的答案可能是:如果您还不知道程序的逻辑,那么您有需要修复的主要基本逻辑错误。

于 2012-09-09T16:20:09.373 回答
34

您可以使用以下fcntl()功能:

int fd_is_valid(int fd)
{
    return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
}
于 2012-09-09T16:20:02.963 回答
6

我认为没有任何函数可以告诉您描述符是否仍然有效。描述符通常只是一个像 6 这样的小整数,如果您关闭文件并稍后打开一个新文件,您的 libc 可以选择重用该数字。

相反,您应该考虑使用dup()来复制文件描述符。通过复制文件描述符而不是在多个位置使用相同的描述符,您可能会更容易知道文件描述符是否仍然有效。您只需要记住在完成后关闭原始描述符和复制的描述符。

于 2012-09-09T16:21:24.117 回答
6

这篇论坛文章:

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

fcntl(GETFL) 可能是您可以对文件描述符执行的最便宜且最不可能失败的操作。特别是,规范建议它不能被信号中断,也不受任何地方持有的任何类型的锁的影响。

于 2012-09-09T16:25:30.023 回答
0

在我看来,如果您想知道它是否仍然指向相同的资源,一种(非完美)方法是fstat()在打开之后对描述符进行处理,然后您可以再次执行此操作并比较结果。.st_mode从&开始S_IFMT,然后从那里开始——它是一个文件系统对象吗?看看.st_dev / .st_ino. 是插座吗?试试getsockname()getpeername()。它不会 100% 确定,但它可以告诉你它是否绝对不一样。

于 2013-02-09T15:24:27.417 回答
-1

我为我解决了这个问题。我不知道它是否可以用于一般用途,但对于串行连接它工作正常(例如/dev/ttyUSB0)!

struct stat s;
fstat(m_fileDescriptor, &s);

// struct stat::nlink_t   st_nlink;   ... number of hard links 
if( s.st_nlink < 1 ){
 // treat device disconnected case
}

有关详细信息,请参见例如手册页http://linux.die.net/man/2/fstat

干杯,弗洛

于 2014-10-10T13:51:55.053 回答