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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12340695/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 14:18:44  来源:igfitidea点击:

How to check if a given file descriptor stored in a variable is still valid?

clinuxgccfile-descriptor

提问by Lunar Mushrooms

I have a file descriptor stored in a variable say var. How can I check whether that descriptor is valid at a later stage?

我有一个文件描述符存储在一个变量中,比如 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, ....);

Now i want to check whether var1 (which still holds the opened descriptor) is still valid. Any API's for that ?

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

采纳答案by R.. GitHub STOP HELPING ICE

fcntl(fd, F_GETFD)is the canonical cheapest way to check that fdis a valid open file descriptor. If you need to batch-check a lot, using pollwith a zero timeout and the eventsmember set to 0 and checking for POLLNVALin reventsafter it returns is more efficient.

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

With that said, the operation "check if a given resource handle is still valid" is almost always fundamentally incorrect. After a resource handle is freed (e.g. a fd is closed), its value may be reassigned to the next such resource you allocate. If there are any remaining references that might be used, they will wrongly operate on the new resource rather than the old one. Thus, the real answer is probably: If you don't already know by the logic of your program, you have major fundamental logic errors that need to be fixed.

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

回答by Lunar Mushrooms

You can use the fcntl()function:

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

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

回答by David Grayson

I don't think there is any function that can tell you if the descriptor is still valid. The descriptor is typically just a small integer like 6 and your libc can choose to reuse that number if you close the file and open a new one later.

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

Instead, you should consider using dup()to copy the file descriptor. By duplicating the file descriptor instead of using the same descriptor in multiple places, it might become easier for you to know whether the file descriptor is still valid. You just have to remember to close both the original descriptor and the duplicated one when you are done.

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

回答by wbao

From thisforum article:

来自这篇论坛文章:

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

fcntl(GETFL) is probably the cheapest and least likely to fail operation you can perform on a file descriptor. In particular, the specification suggests that it cannot be interrupted by signals, nor is it affected by any sort of lock held anywhere.

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

回答by John Hascall

It seems to me that if you want to know if it still points to the same resource, one (non-perfect) approach would be to fstat()the descriptor just after open and then later you can do it again and compare the results. Start by looking at .st_mode& S_IFMTand go from there -- is it a filesystem object? Look at .st_dev / .st_ino.Is it a socket? Try getsockname(), getpeername(). It won't be 100% certain, but it can tell you if it definitely isn't the same.

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

回答by flozn

i solved this problem for me. i don't know whether it can be used for general purpose but for serial connections it works fine (e.g. /dev/ttyUSB0)!

我为我解决了这个问题。我不知道它是否可以用于一般用途,但对于串行连接它工作正常(例如 /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
}

For details see e.g. man page http://linux.die.net/man/2/fstat

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

Cheers, Flo

干杯,弗洛