简体   繁体   English

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

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

I have a file descriptor stored in a variable say var. 我有一个存储在变量var中的文件描述符。 How can I check whether that descriptor is valid at a later stage? 如何在以后的阶段检查该描述符是否有效?

  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. 现在,我想检查var1(仍保留打开的描述符)是否仍然有效。 Any API's for that ? 是否有任何API?

fcntl(fd, F_GETFD) is the canonical cheapest way to check that fd is a valid open file descriptor. fcntl(fd, F_GETFD)是检查fd是有效的打开文件描述符的最便宜的规范方法。 If you need to batch-check a lot, using poll with a zero timeout and the events member set to 0 and checking for POLLNVAL in revents after it returns is more efficient. 如果需要批量查了很多,使用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 (eg a fd is close d), its value may be reassigned to the next such resource you allocate. 释放资源句柄后(例如fd close d),可以将其值重新分配给您分配的下一个此类资源。 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. 因此,真正的答案可能是:如果您尚不了解程序的逻辑,则有一些基本的基本逻辑错误需要修复。

You can use the fcntl() function: 您可以使用fcntl()函数:

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

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. 相反,您应该考虑使用dup()复制文件描述符。 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. 您只需要记住在完成后同时关闭原始描述符和重复的描述符。

From this forum 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. fcntl(GETFL)可能是您可以对文件描述符执行的最便宜,最不可能失败的操作。 In particular, the specification suggests that it cannot be interrupted by signals, nor is it affected by any sort of lock held anywhere. 特别是,该规范建议它不能被信号打断,也不受任何位置的任何锁的影响。

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. 在我看来,如果您想知道它是否仍然指向相同的资源,一种(非完美的)方法是在打开后立即对fstat()描述符进行处理,然后再进行操作并比较结果。 Start by looking at .st_mode & S_IFMT and go from there -- is it a filesystem object? 从查看.st_modeS_IFMT ,然后从那里开始-它是文件系统对象吗? Look at .st_dev / .st_ino. 查看.st_dev / .st_ino. Is it a socket? 是插座吗? Try getsockname() , getpeername() . 尝试getsockname()getpeername() It won't be 100% certain, but it can tell you if it definitely isn't the same. 不确定100%,但是它可以告诉您是否绝对不同。

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 (eg /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 eg man page http://linux.die.net/man/2/fstat 有关详细信息,请参见手册页http://linux.die.net/man/2/fstat

Cheers, Flo 干杯,弗洛

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM