Linux 从 C 中的文件描述符中检索文件名
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1188757/
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
Retrieve filename from file descriptor in C
提问by adk
Is it possible to get the filename of a file descriptor (Linux) in C?
是否可以在 C 中获取文件描述符(Linux)的文件名?
采纳答案by bdonlan
You can use readlink
on /proc/self/fd/NNN
where NNN is the file descriptor. This will give you the name of the file as it was when it was opened — however, if the file was moved or deleted since then, it may no longer be accurate (although Linux can track renames in some cases). To verify, stat
the filename given and fstat
the fd you have, and make sure st_dev
and st_ino
are the same.
您可以使用readlink
在/proc/self/fd/NNN
其中NNN是文件描述符。这将为您提供文件打开时的名称——但是,如果文件从那时起被移动或删除,它可能不再准确(尽管 Linux 在某些情况下可以跟踪重命名)。要验证stat
给定的文件名和fstat
您拥有的 fd,并确保st_dev
和st_ino
相同。
Of course, not all file descriptors refer to files, and for those you'll see some odd text strings, such as pipe:[1538488]
. Since all of the real filenames will be absolute paths, you can determine which these are easily enough. Further, as others have noted, files can have multiple hardlinks pointing to them - this will only report the one it was opened with. If you want to find all names for a given file, you'll just have to traverse the entire filesystem.
当然,并非所有文件描述符都指向文件,对于那些文件,您会看到一些奇怪的文本字符串,例如pipe:[1538488]
. 由于所有真实文件名都是绝对路径,因此您可以很容易地确定哪些是绝对路径。此外,正如其他人所指出的,文件可以有多个指向它们的硬链接 - 这只会报告打开它的那个。如果要查找给定文件的所有名称,只需遍历整个文件系统即可。
回答by Tyler McHenry
Impossible. A file descriptor may have multiple names in the filesystem, or it may have no name at all.
不可能的。文件描述符在文件系统中可能有多个名称,也可能根本没有名称。
Edit: Assuming you are talking about a plain old POSIX system, without any OS-specific APIs, since you didn't specify an OS.
编辑:假设您谈论的是一个普通的旧 POSIX 系统,没有任何特定于操作系统的 API,因为您没有指定操作系统。
回答by Martin v. L?wis
In Windows, with GetFileInformationByHandleEx, passing FileNameInfo, you can retrieve the file name.
在 Windows 中,通过GetFileInformationByHandleEx传递FileNameInfo,您可以检索文件名。
回答by PetrosB
You can use fstat() to get the file's inode by struct stat. Then, using readdir() you can compare the inode you found with those that exist (struct dirent) in a directory (assuming that you know the directory, otherwise you'll have to search the whole filesystem) and find the corresponding file name. Nasty?
您可以使用 fstat() 通过 struct stat 获取文件的 inode。然后,使用 readdir() 可以将找到的 inode 与目录中存在的 inode (struct dirent) 进行比较(假设您知道该目录,否则您将不得不搜索整个文件系统)并找到相应的文件名。可恶的?
回答by Alex Martelli
As Tyler points out, there's no way to do what you require "directly and reliably", since a given FD may correspond to 0 filenames (in various cases) or > 1 (multiple "hard links" is how the latter situation is generally described). If you do still need the functionality with all the limitations (on speed AND on the possibility of getting 0, 2, ... results rather than 1), here's how you can do it: first, fstatthe FD -- this tells you, in the resulting struct stat
, what device the file lives on, how many hard links it has, whether it's a special file, etc. This may already answer your question -- e.g. if 0 hard links you will KNOW there is in fact no corresponding filename on disk.
正如 Tyler 指出的那样,没有办法“直接且可靠地”执行您需要的操作,因为给定的 FD 可能对应于 0 个文件名(在各种情况下)或 > 1 个(多个“硬链接”是后一种情况的一般描述方式) )。如果您仍然需要具有所有限制的功能(在速度上以及获得 0、2、... 结果而不是 1 的可能性),那么您可以这样做:首先,fstat FD——这会告诉您,在结果中struct stat
,文件所在的设备,它有多少个硬链接,它是否是一个特殊文件等。这可能已经回答了您的问题——例如,如果您知道 0 个硬链接,实际上没有相应的文件名磁盘上。
If the stats give you hope, then you have to "walk the tree" of directories on the relevant device until you find all the hard links (or just the first one, if you don't need more than one and any one will do). For that purpose, you use readdir(and opendir &c of course) recursively opening subdirectories until you find in a struct dirent
thus received the same inode number you had in the original struct stat
(at which time if you want the whole path, rather than just the name, you'll need to walk the chain of directories backwards to reconstruct it).
如果统计数据给了您希望,那么您必须在相关设备上“遍历目录树”,直到找到所有硬链接(或者只是第一个,如果您不需要多个,任何一个都可以) )。为此,您使用readdir(当然还有 opendir &c)递归地打开子目录,直到您在 a 中找到struct dirent
与原始目录中相同的 inode 编号struct stat
(此时如果您想要整个路径,而不仅仅是名称,您需要向后遍历目录链以重建它)。
If this general approach is acceptable, but you need more detailed C code, let us know, it won't be hard to write (though I'd rather not write it if it's useless, i.e. you cannot withstand the inevitably slow performance or the possibility of getting != 1 result for the purposes of your application;-).
如果这种通用方法可以接受,但您需要更详细的 C 代码,请告诉我们,它不会很难编写(尽管如果它没有用,我宁愿不写它,即您无法承受不可避免的缓慢性能或为了您的应用程序的目的,获得 != 1 结果的可能性;-)。
回答by Duck
Before writing this off as impossible I suggest you look at the source code of the lsofcommand.
在将此写为不可能之前,我建议您查看lsof命令的源代码。
There may be restrictions but lsof seems capable of determining the file descriptor and file name. This information exists in the /proc filesystem so it should be possible to get at from your program.
可能存在限制,但 lsof 似乎能够确定文件描述符和文件名。此信息存在于 /proc 文件系统中,因此应该可以从您的程序中获取。
回答by zneak
I had this problem on Mac OS X. We don't have a /proc
virtual file system, so the accepted solution cannot work.
我在 Mac OS X 上遇到了这个问题。我们没有/proc
虚拟文件系统,所以接受的解决方案无法工作。
We do, instead, have a F_GETPATH
command for fcntl
:
相反,我们有一个F_GETPATH
命令fcntl
:
F_GETPATH Get the path of the file descriptor Fildes. The argu-
ment must be a buffer of size MAXPATHLEN or greater.
So to get the file associated to a file descriptor, you can use this snippet:
因此,要获取与文件描述符关联的文件,您可以使用以下代码段:
#include <sys/syslimits.h>
#include <fcntl.h>
char filePath[PATH_MAX];
if (fcntl(fd, F_GETPATH, filePath) != -1)
{
// do something with the file path
}
Since I never remember where MAXPATHLEN
is defined, I thought PATH_MAX
from syslimits would be fine.
因为我从不记得MAXPATHLEN
是在哪里定义的,所以我认为PATH_MAX
从 syslimits 就可以了。