9

我想要一个小的“应用程序加载器”程序,它通过 TCP 从外部服务器接收其他二进制应用程序文件并运行它们。

我可以通过将传输的文件保存到硬盘并使用 system() 调用来运行它来做到这一点。但是,我想知道是否可以在不接触硬盘的情况下从内存启动新应用程序。

加载新应用程序后,加载程序应用程序的状态无关紧要。我更喜欢坚持 C,但也欢迎 C++ 解决方案。如果可能的话,我还想坚持使用标准的 Linux C 函数并且不使用任何外部库。

4

3 回答 3

5

简短的回答:没有。

长答案:在不将其写入磁盘的情况下执行此操作是可能的,但相当棘手。从理论上讲,您可以编写自己的 elf 加载器来读取二进制文件、映射一些内存、根据需要处理动态链接,然后转移控制权,但这是大量的工作,几乎不值得付出努力。

下一个最佳解决方案是将其写入磁盘并尽快调用 unlink。磁盘甚至不必是“真正的”磁盘,它可以是 tmpfs 或类似的。

我最近一直在使用的替代方法是不传递完整的编译二进制文件,而是传递 LLVM 字节码,然后可以将其 JIT'd/解释/保存为合适的。这还具有使您的应用程序在异构环境中工作的优势。

尝试组合fmemopen,fileno和可能很诱人fexecve,但这不起作用有两个原因:

  1. fexecve()手册页:

    “文件描述符 fd 必须以只读方式打开,并且调用者必须具有执行它所引用的文件的权限”

    即它必须是一个引用文件的fd。

  2. fmemopen()手册页:

    “没有与这些函数返回的文件流关联的文件描述符(即,fileno(3)如果在返回的流上调用将返回错误)”

于 2012-05-09T20:39:19.620 回答
0

比这样做更容易的是,C 只是设置一个 tmpfs 文件系统。您将拥有硬盘接口的所有优点,从您的程序/服务器/任何您可以做的exec. 这些类型的虚拟文件系统现在非常有效,页面缓存中实际上只有一个可执行文件的副本。

正如 Andy 指出的那样,要使这种方案有效,您必须确保不对文件使用缓冲写入,而是直接在原地“写入”(在更广泛的意义上)。

  • 你必须知道你的可执行文件有多大
  • 在你的 tmpfs 上创建一个文件
  • 将其缩放到那个大小ftruncate
  • 将该文件“映射”到内存中mmap以获取缓冲区的地址
  • 将该地址直接传递给recv调用以将数据写入到位
  • munmap文件
  • exec用文件调用
  • rm文件。即使可执行文件仍在运行也可以完成
于 2012-05-09T21:05:25.673 回答
0

您可能想查看并重用UPX,它将可执行文件解压缩到内存,然后将控制权转移ld-linux到启动它。

于 2012-05-09T21:52:40.993 回答