我是否可以调整写入磁盘的函数以写入内存

时间:2018-05-23 18:42:03

标签: c posix

我有第三方库,其中包含对指定数据执行某些计算的函数,并将结果写入由文件名指定的文件:

int manipulateAndWrite(const char *filename,
                       const FOO_DATA *data);

无法更改此功能,或在我自己的功能中重新实现计算,因为我没有源。

要获得结果,我目前需要从文件中读取它们。我宁愿避免写入和读取文件,而是将结果转换为内存缓冲区。

我是否可以传递指示写入内存而不是a的文件路径 文件系统?

1 个答案:

答案 0 :(得分:1)

是的,你有几个选择,虽然POSIX只支持下面的第一个建议。其余的都是特定于操作系统的,并且可能无法在所有POSIX系统上移植,尽管我相信它们适用于所有POSIXy系统。

  • 您可以使用命名管道(FIFO),并在写入器函数的同时从中读取辅助线程。

    因为本身没有文件,所以开销只是系统调用(写入和读取);基本上只是进程间通信的开销,没什么好担心的。为了节省资源,请使用小堆栈(使用pthread_attr_等)创建辅助线程,因为默认堆栈大小往往很大(大约几兆字节; 2*PTHREAD_STACK_SIZE应该足够辅助线程。)

    您应确保命名管道位于安全目录中,例如,只有运行该流程的用户才能访问该目录。

  • 在许多POSIXy系统中,您可以创建管道或套接字对,并通过/dev/fd/N访问它,其中N是十进制的描述符编号。 (在Linux中,/proc/self/fd/N也有效。)这不是POSIX强制要求的,因此可能并非在所有系统上都可用,但大多数系统都支持它。

    这样,本身没有实际文件,函数会写入管道或套接字。如果函数写入的数据最多为PIPE_BUF个字节,则可以直接读取管道中的数据;否则,你需要创建一个辅助线程来同时从管道或套接字读取函数,否则写将阻塞。

    在这种情况下,开销也很小。

  • 在基于ELF的POSIXy系统(基本上全部)上,您可以插入 open()write()close()系统调用或C库功能

    (在Linux中,有两种基本方法,一种使用链接器--wrap,另一种使用dlsym()。两种方法都适用于这种特殊情况。这种插入函数的能力是基于ELF的方式二进制文件在运行时链接,与POSIX没有直接关系。)

    首先设置插入函数,以便open()检测文件名是否与特殊的“内存”文件匹配,并为其返回专用的描述符编号。 (您可能还需要插入其他函数,例如ftruncate()lseek(),具体取决于函数的实际功能;在Linux中,您可以在ptrace下运行二进制文件来检查它是什么系统调用实际使用。)

    当使用专用描述符编号调用write()时,您只需memcpy()到内存缓冲区。您需要使用全局变量来描述分配的大小,使用的大小以及指向内存缓冲区的指针,并且可能准备在必要时调整大小/增大缓冲区。

    当使用专用描述符编号调用close()时,您知道内存缓冲区已完成,并且内容已准备好进行处理。

  • 您可以在RAM文件系统上使用临时文件。虽然数据在技术上写入文件并从中读回,但操作仅涉及RAM。

    您应该安排在编译时设置的默认路径,并且个别用户可以根据个人需要覆盖该路径,例如通过环境变量(YOURAPP_TMPDIR?)。 / p>

    应用程序无需尝试查找基于RAM的文件系统:这样的选择是,应该由用户决定。应用程序甚至不应该关心文件所在的文件系统类型,而应该只使用指定的目录。