在Linux中是否存在系统调用或其他方法可以知道文件描述符的类型(例如常规文件fd,socket fd,signal fd,timer fd)?

3

我发现,有各种各样的文件描述符——几乎每件事情都是围绕着文件描述符抽象化的:常规文件、套接字、信号和计时器(例如)。所有文件描述符只是整数。

给定一个文件描述符,是否可以知道它是什么类型?例如,拥有像 getFdType(fd) 这样的系统调用会很好。

如果 epoll_wait 由于多个文件描述符准备就绪而被唤醒,则每个文件描述符的处理将基于其类型。这就是我需要该类型的原因。

当然,我可以自己单独维护此信息,但使用系统支持会更加方便。

此外,不管类型如何,所有文件描述符是否都是连续的?也就是说,如果你打开一个常规数据文件,然后创建一个计时器文件描述符,再创建一个信号文件描述符,它们是否都保证按顺序编号?


1
最好询问例如检查任意FD以进行调试/分析原因,而不是将其用于epoll决策,因为这是如此限制性的设计决策和架构死胡同。据我所知,没有像getFdType这样的东西,但传统上有fstat来区分类似文件的类型,并尝试使用fd特定调用,例如getsockopttimerfd_gettime来区分它们,作为最后的手段,可以使用/proc/1234/fd/42上的readlink获取描述性字符串,例如anon_inode:[timerfd] - that other guy
这是fstat调用。https://linux.die.net/man/2/fstat - stark
@thatotherguy:“因为这是一个如此严格的设计决策和架构死胡同。” 你能详细说明一下吗?如果需要,我对架构变更持开放态度。 - asinix
1
大多数服务器都需要为每个FD提供额外的上下文和元数据,例如其当前协议特定状态/标志、发送/接收队列或位置、水印/重试信息等。 - that other guy
@thatotherguy 我已经处理了这个方面。我的fdData结构保留了这样的信息。我认为Nate观察到如果有系统调用可用,使用它将是昂贵的,这是我没有想到的。 - asinix
@那个其他人,你的第一条评论充满了有用的信息。但愿我能多次点赞它... - asinix
1个回答

2
正如“其他人”所提到的一样,最明显的调用是fstat。其中的st_mode成员包含区分常规文件、设备、套接字、管道等的位。
但实际上,在你打开几个不同的常规文件时,知道它是常规文件并没有太大帮助,你几乎肯定需要自己跟踪每个fd。因此,由于你必须在代码中维护这些信息,因此回到记录中似乎是最健壮的方法。
(在程序内检查一些变量要比进行一个或多个额外的系统调用快得多。)
此外,无论类型如何,所有文件描述符都是连续的吗?我的意思是,如果你打开一个常规数据文件,然后创建一个计时器文件描述符,再创建一个信号文件描述符,它们是否都保证按顺序编号?
不完全是这样。
据我所知,调用创建新fd将始终返回可用fd中编号最低的fd。有些旧程序依赖于此行为;在dup2存在之前,我相信将标准输入移动到新文件的接受方法是close(0); open("myfile", ...);.
但是,真正确定哪些fds可用很难。例如,用户可能已将您的程序运行为/usr/bin/prog 5>/some/file/somewhere,然后将会跳过fd 5,因为/some/file/somewhere已经在fd 5上打开。因此,如果您连续打开一堆文件,则无法确定是否会获得连续的fds,除非您刚刚关闭了所有这些fds并且确信所有较低编号的fds已经在使用中。这似乎比一开始就跟踪fds要麻烦得多(也是潜在问题的来源)。

“(在程序中检查一些变量要比进行一个或多个额外的系统调用快得多)”是我个人认为你回答中的关键点。 - asinix
好吧,我不想过分强调这一点,因为在许多程序中,无论如何它都只占总执行时间的微不足道的一部分。但是我想加入一些东西,以迎合那些无法抗拒不必要优化的人们的兴趣;-) - Nate Eldredge

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接