在C中从文件描述符检索文件名

在C中从文件描述符检索文件名,c,linux,file,file-descriptor,C,Linux,File,File Descriptor,可以用C语言获取文件描述符(Linux)的文件名吗?不可能。文件描述符在文件系统中可能有多个名称,或者根本没有名称 编辑:假设您谈论的是一个普通的旧POSIX系统,没有任何特定于操作系统的API,因为您没有指定操作系统。在Windows中,通过,您可以检索文件名。您可以使用fstat()通过struct stat获取文件的inode。然后,使用readdir()可以将找到的inode与存在的inode进行比较(struct dirent)并找到相应的文件名。 讨厌?正如泰勒所指出的,没有办法“直

可以用C语言获取文件描述符(Linux)的文件名吗?

不可能。文件描述符在文件系统中可能有多个名称,或者根本没有名称

编辑:假设您谈论的是一个普通的旧POSIX系统,没有任何特定于操作系统的API,因为您没有指定操作系统。

在Windows中,通过,您可以检索文件名。

您可以使用fstat()通过struct stat获取文件的inode。然后,使用readdir()可以将找到的inode与存在的inode进行比较(struct dirent)并找到相应的文件名。
讨厌?

正如泰勒所指出的,没有办法“直接可靠地”完成您需要的工作,因为给定的FD可能对应于0个文件名(在各种情况下)或>1(后一种情况通常描述为多个“硬链接”)。如果您确实需要具有所有限制的功能(关于速度和获得0,2,…结果而不是1的可能性)首先,FD——它告诉你,在生成的
struct stat
中,文件所在的设备,它有多少个硬链接,它是否是一个特殊的文件,等等。这可能已经回答了你的问题——例如,如果有0个硬链接,你就会知道磁盘上实际上没有相应的文件名

如果统计数据给了你希望,那么你必须在相关设备上“遍历目录树”,直到找到所有的硬链接(或者只有第一个,如果你不需要多个,任何一个都可以)。为此,你使用(当然还有opendir&c)递归地打开子目录,直到在
struct dirent
中找到,从而收到与原始
struct stat
中相同的inode编号(此时,如果需要整个路径,而不仅仅是名称,则需要向后遍历目录链以重建它)


如果这种通用方法是可以接受的,但您需要更详细的C代码,请让我们知道,编写它并不困难(尽管如果它没有用,我宁愿不编写它,也就是说,您无法承受不可避免的缓慢性能,或者在应用程序中获得!=1结果的可能性;-).

在将此视为不可能之前,我建议您查看该命令的源代码

可能有限制,但lsof似乎能够确定文件描述符和文件名。此信息存在于/proc文件系统中,因此可以从您的程序中获取。

您可以在
/proc/self/fd/NNN
上使用,其中NNN是文件描述符。这将为您提供文件创建时的名称已打开-但是,如果文件从那时起被移动或删除,它可能不再准确(尽管Linux在某些情况下可以跟踪重命名)。要验证,
stat
给定的文件名和
fstat
您拥有的fd,并确保
st_dev
st_ino
是相同的


当然,并非所有的文件描述符都引用文件,对于这些描述符,您将看到一些奇怪的文本字符串,例如
pipe:[1538488]
。由于所有实际文件名都是绝对路径,因此您可以很容易地确定哪些路径是绝对路径。此外,正如其他人所指出的,文件可以有多个指向它们的硬链接-这将只报告打开文件时使用的硬链接。如果您想找到给定文件的所有名称,只需遍历整个文件系统即可

我在Mac OS X上遇到了这个问题。我们没有
/proc
虚拟文件系统,因此公认的解决方案无法工作

相反,我们有一个用于
fcntl
F_GETPATH
命令:

 F_GETPATH          Get the path of the file descriptor Fildes.  The argu-
                    ment must be a buffer of size MAXPATHLEN or greater.
因此,要获取与文件描述符关联的文件,可以使用以下代码段:

#include <sys/syslimits.h>
#include <fcntl.h>

char filePath[PATH_MAX];
if (fcntl(fd, F_GETPATH, filePath) != -1)
{
    // do something with the file path
}
#包括
#包括
char filePath[PATH_MAX];
如果(fcntl(fd,F_GETPATH,filePath)!=-1)
{
//对文件路径执行一些操作
}

因为我从来都不记得
MAXPATHLEN
是在哪里定义的,所以我认为来自syslimits的
PATH\u MAX
就可以了。

然后我的答案就适用了。Linux没有这样做的工具。Linux(POSIX)文件描述符不一定指文件,即使它们指的是索引节点,也不是文件名。描述符可以指向已删除的文件(因此没有名称,这是生成临时文件的常见方法),也可以指向具有多个名称的索引节点(硬链接)。请尝试查看lsof源代码:)不久前我自己也遇到同样的问题时,我就是这么做的。lsof在黑魔法和牺牲山羊身上工作——你不能希望复制它的行为。更具体地说,lsof与linux内核紧密耦合,不通过用户代码可用的任何API来做它所做的事情。linux有一个不可移植的过程API对于这一点,确实存在一些限制,但说这是不可能的完全是错误的。@Tyler-lsof在用户空间中运行。因此,无论它做什么,都有一个API可用于userland代码:)@Duck,那里的可移植性可能就是lsof的源代码有这么多黑魔法的原因;每个UNIX变体都有不同的功能。linux proc接口还不错,事实上,alebit的文档很少。虽然我讨厌windows,但只要原始文件仍然有引用(open
fd
就是这样的引用),就可以使用windows等效接口,inode编号不能重复使用。任何在关闭文件后或打开文件前使用inode编号的软件都会受到竞争条件的影响。危险,威尔·罗宾逊!这并不总是有效的——如果您使用
setuid()
技巧,您的进程可能无法访问
/proc/self/fd
。请参阅:@bdonlan:如果没有挂载/proc?@user2284570,这个答案是特定于Linux的。我不知道NetBSD是否支持procfs—如果