C语言 具有自己的文件偏移量的重复文件描述符

zqdjd7g9  于 2023-02-15  发布在  其他
关注(0)|答案(4)|浏览(149)

如何从现有的文件描述符创建新的文件描述符,使新的描述符不共享文件表中相同的内部文件结构/条目?具体而言,诸如文件偏移量(最好是权限、共享和模式)等属性不应在新旧文件描述符之间共享。
在Windows和Linux下,dup()都将复制文件描述符,但这两个描述符仍然指向进程文件表中的同一个文件结构。在其中一个描述符上的任何查找都将调整其他描述符的位置。

    • 注**

从那以后,我收到了针对Windows和Linux的答案,并且对问题进行了太多次调整,这使得人们很难回答。我将调整我的投票,接受涵盖Windows * 和 * Linux的最清晰的答案。向大家道歉,我对SO范式还是个新手。感谢你们的精彩回答!

plupiseo

plupiseo1#

基本上,您真正需要的是获得一个文件描述符,然后重新打开同一个文件,以获得一个单独的位置、共享、模式等。您希望在Windows上执行此操作(在Windows上,“文件描述符”基本上是一个外来对象,根本不是操作系统 * 或 * 运行时库直接使用的对象)。
令人惊讶的是,至少在MSVC ++中,有一种方法可以做到这一点。除了两个步骤外,所有步骤都只使用Win32 API,因此移植到其他编译器/库应该是相当合理的(我认为大多数提供这两个函数的版本)。这两个函数用于将Unix风格的文件描述符转换为原生Win32文件句柄,以及将本地Win32文件句柄转换回Unix风格的文件描述符。
1.使用_get_osfhandle()将文件描述符转换为本机文件句柄
1.使用GetFileInformationByHandleEx(文件名信息)1获取文件的名称
1.使用CreateFile打开该文件的新句柄
1.使用_open_osfhandle()为该句柄创建文件描述符

  • 瞧 *,我们有一个新的文件描述符引用同一个文件,但有自己的权限,位置等.

在问题的最后,您说得好像您也想要“权限”,但这似乎没有任何真实的意义--权限附加到文件本身,而不是文件的打开方式,因此打开或重新打开文件对文件的权限没有影响。但请注意,Windows中的文件权限与Unix中的(传统的)文件权限。Unix对所有文件都有所有者/组/全局权限,并且大多数系统也有ACL(尽管它们的工作方式有更多的变化)。Windows要么根本没有权限(例如,FAT或FAT32上的文件)或使用ACL(例如,NTFS上的文件),但没有什么真正等同于大多数人在Unix上习惯的传统所有者/组/全局权限。
也许你用“权限”来表示文件是否可以阅读、写或两者都打开。获得这个权限比前面的任何一个都要丑陋得多。问题是它的大部分都在库中,而不是Win32中。所以可能没有办法做到这一点,甚至将接近可移植的编译器之间。(不保证适用于 * 任何 * 其他编译器)您可以这样做:

#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.
}

由于这涉及到一些洞穴探险,我写了一个快速测试来验证它是否真的可以工作:

#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

而结果似乎预示着成功:

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

然后,您可以针对_IOREAD、_IOWRT和_IORW测试返回的标志,这些标志在stdio. h中定义。尽管我前面提出了警告,但我可能应该指出,我怀疑(尽管我当然不能保证)库的这一部分相当稳定,因此进行重大更改的真实的机会可能相当小。
然而,在另一个方向上,它基本上不可能与任何其他库一起工作。它可以(但肯定不能保证)与其他使用MS库的编译器一起工作,如Intel、MinGW或使用MS VC++作为后端的Comeau。在这些编译器中,我认为最有可能工作的是Comeau,最不可能的是MinGW(但这只是一个猜测;很有可能它对它们中的任何一个都不起作用)。
1.需要可再发行的Win32 FileID API Library

pexxcrt2

pexxcrt22#

所以,我建议多阅读一点,dup()和相关函数用于在文件描述符表中创建一个重复的值,指向打开文件表中的相同条目,这是预期具有相同的偏移量,如果你调用open(),你将在打开文件表中创建一个新条目。
创建一个文件描述符的副本并且新的文件描述符在打开文件表中具有不同的偏移量是没有任何意义的(这似乎与单词“duplicate”的含义相矛盾)。
我不知道你的问题到底是什么。我的意思是,它和重复的问题不是一回事。你可以这样读:
/proc/self/fd/[descriptor]
并获取用于打开该文件描述符的字符串;请记住,这可能会带来一些陷阱,其中一些陷阱实际上是您在再次调用open()时观察到的。
也许你可以解释多一点,我可以尝试更新,以帮助。

wydwbb8l

wydwbb8l3#

为什么不在windows上用open()或CreateFile()再次打开文件呢?这给了你不同访问权限和不同偏移量的自由。
这当然有一个缺点,你不能打开文件独占,但它解决你的问题非常简单。

ymzxtsji

ymzxtsji4#

对于那些不理解为什么要在“复制”描述符上使用独立文件指针的人来说,多个线程可以独立地对文件进行操作。创建独立文件描述符或文件指针的标准方法包括为每个线程重新打开文件,但这会产生一个争用条件,在所有线程都获得其文件指针之前,原始文件可能会被重命名或移动。

相关问题