如何检查存储在变量中的给定文件描述符是否仍然有效?

Lun*_*oms 44 c linux gcc file-descriptor

我有一个文件描述符存储在变量say 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, ....);
Run Code Online (Sandbox Code Playgroud)

现在我想检查var1(仍保留打开的描述符)是否仍然有效.任何API都是为了什么?

R..*_*R.. 74

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

话虽如此,"检查给定资源句柄是否仍然有效"的操作几乎总是根本不正确.在释放资源句柄(例如,fd为closed)之后,可以将其值重新分配给您分配的下一个此类资源.如果存在可能使用的任何剩余引用,则它们将错误地操作新资源而不是旧资源.因此,真正的答案可能是:如果您还不了解程序的逻辑,则会出现需要修复的主要基本逻辑错误.


小智 23

你可以使用这个fcntl()功能:

int fd_is_valid(int fd)
{
    return fcntl(fd, F_GETFD) != -1 || errno != EBADF;
}
Run Code Online (Sandbox Code Playgroud)

  • @Bilow 他已经在检查 `-1` 的返回值,这只会在“出现错误的情况下”发生,因此在调用之前将 `errno` 设置为 0 只是多余的。 (4认同)
  • `F_GETFD`原则上更便宜,因为它只取消引用内核空间中的(进程本地)文件描述符,而不是它引用的底层打开文件描述(进程共享). (3认同)
  • 在调用`fcntl`之前,你应该将`errno`设置为零.在调用函数之前,`errno`可以等于`EBADF`,`fcntl`只会在出错时更改它. (2认同)
  • @CraigBarnes 确实 (2认同)

小智 6

来自这篇论坛文章:

int is_valid_fd(int fd)
{
    return fcntl(fd, F_GETFL) != -1 || errno != EBADF;
}
Run Code Online (Sandbox Code Playgroud)

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

  • 如何归因您的来源:http://cboard.cprogramming.com/networking-device-communication/93683-checking-if-file-descriptor-valid.html#post678998 (3认同)

Dav*_*son 5

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

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

  • 大卫是"正确的",因为你无法确定描述符是否"*仍然*有效".您可以判断它是否有效,但是这不会提供有关它是否仍然引用相同资源的信息. (4认同)
  • 是.我对有效的定义是它仍然指向过去的相同.我认为这是一个很好的定义,因为它通常是你想要的,你可以通过查看代码来判断描述符是否仍然有效; 它不依赖于未定义的行为. (2认同)
  • 另外,对于OP的特殊问题*,使用`dup`是一个不错的建议*.这将避免整个问题.更好的方法可能是在一个单独的变量中保留一个标志,指示文件描述符是否已经关闭; 这将避免额外的内核空间(以及稀缺的资源消耗). (2认同)