windows 具有自己的文件偏移量的重复文件描述符

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1598586/
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-09-15 13:19:02  来源:igfitidea点击:

Duplicate file descriptor with its own file offset

cwindowslinuxunixfile-descriptor

提问by Matt Joiner

How can one create a new file descriptor from an existing file descriptor such that the new descriptor does not share the same internal file structure/entry in the file table? Specifically attributes such as file offset (and preferably permissions, sharing and modes) should not be shared between the new and old file descriptors.

如何从现有文件描述符创建新文件描述符,以便新描述符不共享文件表中相同的内部文件结构/条目?特别是文件偏移(最好是权限、共享和模式)等属性不应在新旧文件描述符之间共享。

Under both Windows and Linux, dup()will duplicate the file descriptor, but both descriptors still point to the same file structure in the process' file table. Any seeking on either descriptor will adjust the position for the other descriptors as well.

在 Windows 和 Linux 下,dup()都会复制文件描述符,但两个描述符仍然指向进程文件表中相同的文件结构。对任一描述符的任何搜索也将调整其他描述符的位置。

Note

笔记

I've since received answers for both Windows and Linux and adjusted the question a little too often, which has made it difficult for people to answer. I'll adjust my votes and accept the cleanest answer which covers both Windows andLinux. Apologies to all, I'm still new to the SO paradigm. Thanks for the great answers!

从那以后,我收到了 Windows 和 Linux 的答案,并且过于频繁地调整了问题,这让人们很难回答。我会调整我的投票并接受涵盖 WindowsLinux的最干净的答案。向所有人道歉,我还是 SO 范式的新手。谢谢你的好答案!

采纳答案by Jerry Coffin

So basically, what you really want is to be given a file descriptor, and basically open the same file over again, to get a separate position, sharing, mode, etc. And you want to do this on Windows (where the "file descriptor" is basically a foreign object, not something used directly by the OS orthe run-time library at all.

所以基本上,你真正想要的是得到一个文件描述符,基本上再次打开同一个文件,以获得一个单独的位置、共享、模式等。你想在 Windows 上做到这一点(“文件描述符” " 基本上是一个外来对象,根本不是操作系统运行时库直接使用的东西。

Amazingly enough, there isa way to do that, at least with MS VC++. All but two steps of it use only the Win32 API so porting to other compilers/libraries should be fairly reasonable (I think most supply versions of those two functions). Those are for converting a Unix-style file descriptor to a native Win32 file handle, and converting a native Win32 file handle back to a Unix-style file descriptor.

令人吃惊的是,有一个办法做到这一点,至少与MS VC ++。除了两个步骤之外的所有步骤都只使用 Win32 API,因此移植到其他编译器/库应该是相当合理的(我认为这两个函数的大多数供应版本)。这些用于将 Unix 样式的文件描述符转换为本机 Win32 文件句柄,并将本机 Win32 文件句柄转换回 Unix 样式文件描述符。

  1. Convert file-descriptor to native file handle with _get_osfhandle()
  2. Get a name for the file with GetFileInformationByHandleEx(FILE_NAME_INFO)1
  3. Use CreateFile to open a new handle to that file
  4. Create a file descriptor for that handle with _open_osfhandle()
  1. 使用 _get_osfhandle() 将文件描述符转换为本机文件句柄
  2. 使用 GetFileInformationByHandleEx(FILE_NAME_INFO) 1获取文件的名称
  3. 使用 CreateFile 打开该文件的新句柄
  4. 使用 _open_osfhandle() 为该句柄创建文件描述符

Et voilà, we have a new file descriptor referring to the same file, but with its own permissions, position, etc.

等等,我们有一个新的文件描述符指向同一个文件,但有自己的权限、位置等。

Toward the end of your question, you make it sound like you also want the "permissions", but that doesn't seem to make any real sense -- the permissions attach to the file itself, not to how the file is opened, so opening or reopening the file has no effect on the file's permissions. If you really want to know the, you can get it with GetFileInformationByHandle, but be aware that file permissions in Windows are quite a bit different from the (traditional) file permissions in Unix. Unix has owner/group/world permissions on all files, and most systems also have ACLs (though there's more variation in how they work). Windows either has no permissions at all (e.g., files on FAT or FAT32) or else uses ACLs (e.g., files on NTFS), but nothing that's really equivalent to the traditional owner/group/world permissions most people are accustomed to on Unix.

在您的问题结束时,您听起来好像还想要“权限”,但这似乎没有任何实际意义——权限附加到文件本身,而不是文件的打开方式,所以打开或重新打开文件不会影响文件的权限。如果你真的想知道,你可以通过 GetFileInformationByHandle 得到它,但要注意 Windows 中的文件权限与 Unix 中的(传统)文件权限有很大不同。Unix 对所有文件具有所有者/组/世界权限,并且大多数系统也具有 ACL(尽管它们的工作方式有更多变化)。Windows 要么根本没有权限(例如,FAT 或 FAT32 上的文件),要么使用 ACL(例如,NTFS 上的文件),但没有“

Perhaps you're using "permissions" to refer to whether the file was open for reading, writing, or both. Getting that is considerably uglier than any of the preceding. The problem is that most of it is in the library, not Win32, so there's probably no way to do it that will be even close to portable between compilers. With MS VC++ 9.0 SP1 (not guaranteed for anyother compiler) you can do this:

也许您正在使用“权限”来表示文件是否已打开进行读取、写入或两者兼而有之。得到它比之前的任何一个都要丑陋得多。问题是大部分都在库中,而不是 Win32,所以可能没有办法做到甚至接近编译器之间的可移植性。使用 MS VC++ 9.0 SP1(不保证适用于任何其他编译器),您可以执行以下操作:

#include <stdio.h>

int get_perms(int fd) {
    int i;
 FILE * base = __iob_func();

    for (i=0; i<_IOB_ENTRIES; i++) 
        if (base[i]._file == fd)
            return base[i]._flag;     // we've found our file
    return 0; // file wasn't found.
}

Since this involved some spelunking, I wrote a quick test to verify that it might actually work:

由于这涉及一些探索,我写了一个快速测试来验证它是否真的有效:

#ifdef TEST
#include <io.h>

void show_perms(int perms, char const *caption) { 
 printf("File opened for %s\n", caption);
 printf("Read permission = %d\n", (perms & _IOREAD)!=0);
 printf("Write permission = %d\n", (perms & _IOWRT)!=0);
}

int main(int argc, char **argv) { 
 FILE *file1, *file2;
 int perms1, perms2;

 file1=fopen(argv[1], "w");
 perms1 = get_perms(_fileno(file1));
 fclose(file1);

 file2=fopen(argv[1], "r");
 perms2 = get_perms(_fileno(file2));
 fclose(file2);

 show_perms(perms1, "writing");
 show_perms(perms2, "reading");
 return 0;
}
#endif

And the results seem to indicate success:

结果似乎表明成功:

File opened for writing
Read permission = 0
Write permission = 1
File opened for reading
Read permission = 1
Write permission = 0

You can then test that returned flag against _IOREAD, _IOWRT, and _IORW, which are defined in stdio.h. Despite my previous warnings, I should probably point out that I suspect (though I certainly can't guarantee) that this part of the library is fairly stable, so the real chances of major changes are probably fairly minimal.

然后,您可以针对 stdio.h 中定义的 _IOREAD、_IOWRT 和 _IORW 测试返回的标志。尽管我之前有过警告,但我可能应该指出,我怀疑(尽管我当然不能保证)库的这一部分相当稳定,因此发生重大变化的真正机会可能相当小。

In the other direction, however, there's basically no chance at allthat it'll work with any other library. It could(but certainly isn't guaranteed to) work with the other compilers that use the MS library, such as Intel, MinGW or Comeau using MS VC++ as its back-end. Of those, I'd say the most likely to work would be Comeau, and the least likely MinGW (but that's only a guess; there's a good chance it won't work with any of them).

在另一个方向,然而,基本上没有机会可言,它会与任何其他库工作。它可以(但肯定不能保证)与使用 MS 库的其他编译器一起工作,例如使用 MS VC++ 作为后端的 Intel、MinGW 或 Comeau。其中,我认为最有可能起作用的是 Comeau,而 MinGW 的可能性最小(但这只是一个猜测;很有可能它对它们中的任何一个都不起作用)。

  1. Requires the redistributable Win32 FileID API Library
  1. 需要可再发行的Win32 FileID API 库

回答by BobbyShaftoe

So, I recommend reading up on this a little more. The dup()and related functions serve to create a duplicate value in the file descriptor table pointing to the same entry in the open file table. This is intendedto have the same offset. If you call open(), you will create a new entry the open file table.

所以,我建议多读一点。在dup()和相关功能用于创建该文件描述符表指向一个重复的值在打开文件表相同的条目。这旨在具有相同的偏移量。如果您调用open(),您将在打开的文件表中创建一个新条目。

It doesn't make any sense to create a duplicate of a file descriptor and that new file descriptor have a different offset in the open file table (this seems to contradict what the word "duplicate" means).

创建文件描述符的副本没有任何意义,并且新文件描述符在打开的文件表中具有不同的偏移量(这似乎与“重复”一词的含义相矛盾)。

I'm not sure what your question is actually. I mean, it isn't the same thing as a duplicate. You could read:

我不确定你的问题实际上是什么。我的意思是,它与复制品不同。你可以读:

/proc/self/fd/[descriptor]

/proc/self/fd/[descriptor]

and get the string that was used to open that file descriptor; bear in mind this may provide some pitfalls, some of which you actually noted in your observation of calling open()again.

并获取用于打开该文件描述符的字符串;请记住,这可能会带来一些陷阱,其中一些是您在观察open()再次调用时实际注意到的。

Maybe you can explain a little more and I can try to update to help.

也许您可以多解释一下,我可以尝试更新以提供帮助。

回答by RED SOFT ADAIR

Why don't you just open the file a second time with open() or CreateFile() on windows? This gives you all freedom of different access rights and separate offset.

为什么不在 Windows 上使用 open() 或 CreateFile() 再次打开文件?这为您提供了不同访问权限和单独偏移的所有自由。

This of course has the drawback that you you can not open the file exclusively, but it solves your problem very simply.

这当然有一个缺点,你不能以独占方式打开文件,但它非常简单地解决了你的问题。