代码之家  ›  专栏  ›  技术社区  ›  Matt Joiner

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

  •  15
  • Matt Joiner  · 技术社区  · 15 年前

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

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

    注释

    从那时起,我就收到了Windows和Linux的答案,并且对这个问题进行了过多次的调整,这使得人们很难回答这个问题。我会调整我的投票,接受最清楚的答案,包括两个窗口 Linux。向所有人道歉,我还是一个新手。谢谢你的回答!

    3 回复  |  直到 15 年前
        1
  •  12
  •   Jerry Coffin    15 年前

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

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

    1. 使用_get_osfhandle()将文件描述符转换为本机文件句柄
    2. 使用getfileinformationByhandleex(文件名\u info)获取文件名
    3. 使用createfile打开该文件的新句柄
    4. 使用“打开”osfhandle()为该句柄创建文件描述符

    埃特维尔石油公司 ,我们有一个新的文件描述符引用同一个文件,但是它有自己的权限、位置等。

    在问题的最后,您让它听起来像您还需要“权限”,但这似乎没有任何实际意义——权限附加到文件本身,而不是文件的打开方式,因此打开或重新打开文件对文件的权限没有影响。如果您真的想知道,可以通过getfileinformationByhandle获得它,但是请注意,Windows中的文件权限与UNIX中的(传统)文件权限有很大的不同。Unix对所有文件都有所有者/组/世界权限,大多数系统也有ACL(尽管它们的工作方式有更多的变化)。Windows或者根本没有权限(例如,FAT或FAT32上的文件),或者使用ACL(例如,NTFS上的文件),但是没有任何东西真正等同于大多数人在Unix上习惯的传统所有者/组/世界权限。

    也许您正在使用“权限”来指代该文件是为读、写还是同时打开。这比前面的任何一个都要糟糕得多。问题是,它的大部分都在库中,而不是在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.
    }
    

    因为这涉及到一些洞穴探险,我写了一个快速测试来验证它是否真的有效:

    #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
    

    然后,您可以测试返回的标志与stdio.h中定义的“旧”、“旧”和“旧”进行对比。尽管我以前警告过,但我可能应该指出,我怀疑(尽管我当然不能保证)库的这一部分相当稳定,因此进行重大更改的真正机会可能相当小。

    然而,在另一个方向,基本上没有机会 完全 它可以和其他图书馆一起使用。它 能够 (但当然不能保证)与其他使用MS库的编译器一起工作,如Intel、Mingw或Comeau,使用MS VC++作为后端。其中,我想说最有可能工作的是科莫,最不可能是明格(但这只是一个猜测;很有可能它不会与任何人一起工作)。

    1. 需要可再发行的 Win32 FileID API Library
        2
  •  2
  •   BobbyShaftoe    15 年前

    所以,我建议多读一点。这个 dup() 相关函数用于在文件描述符表中创建指向打开文件表中同一条目的重复值。这是 打算 具有相同的偏移量。如果你打电话 open() ,您将创建一个新条目“打开的文件”表。

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

    我不知道你的问题到底是什么。我是说,这和复制品不一样。你可以阅读:

    /proc/self/fd/[descriptor]

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

    也许你可以解释更多,我可以尝试更新帮助。

        3
  •  0
  •   RED SOFT ADAIR    15 年前

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

    当然,这有一个缺点,即您不能以独占方式打开文件,但它可以很简单地解决您的问题。