【问题标题】:Can I adapt a function that writes to disk to write to memory我可以调整一个写入磁盘的函数来写入内存吗
【发布时间】:2018-05-23 18:42:03
【问题描述】:

我有一个带有函数的第三方库,它对指定的数据进行一些计算,并将结果写入由文件名指定的文件:

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

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

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

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

【问题讨论】:

  • 是的,使用 RAM 驱动器路径。相关:stackoverflow.com/questions/36706602/…
  • 在哪个操作系统上????
  • 在 Linux 和 Windows 上都存在创建 RAM 磁盘并从该 RAM 磁盘传递文件路径的解决方案。它不写入磁盘。请注意,如果文件很小,如果立即重新读取并删除,则写入临时目录根本不会写入磁盘。
  • 这个第三方库的设计有问题。允许写入 FILE * 对象将为您提供更多选择。
  • @Jean-FrançoisFabre 是的,但在 Debian 和衍生产品上,您可以轻松地读取/写入 /dev/shm

标签: c posix


【解决方案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?)。

    应用程序无需尝试寻找基于 RAM 的文件系统:像这样的选择是并且应该由用户决定。应用程序甚至不应该关心文件在哪种文件系统上,而应该只使用指定的目录。

【讨论】:

    【解决方案2】:

    您无法使用该库函数。看一下如何写入内存文件: Is it possible to create a C FILE object to read/write in memory

    【讨论】:

    • 这个链接没有帮助,因为它不相关。
    • 他要求选项,问题用 c 和 POSIX 标记。链接怎么不相关?
    • 因为 OP 在开始的界面中没有FILE 对象
    • 因此这是一个选项。使用他的库函数的替代方法。
    • 这不是我的库函数。问题是我需要捕获此函数正在执行的其他数据操作,而不会受到磁盘损坏的影响。
    猜你喜欢
    • 1970-01-01
    • 2010-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-13
    • 1970-01-01
    • 1970-01-01
    • 2012-04-13
    相关资源
    最近更新 更多