【问题标题】:Execute a process from memory within another process?从另一个进程中的内存执行一个进程?
【发布时间】:2012-05-18 09:59:41
【问题描述】:

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

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

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

【问题讨论】:

  • 是的,这是可能的,但它有点复杂。您必须模拟操作系统并将二进制文件映射到内存等。
  • 你可以把它写到 ramdisk 上的一个文件中
  • 我也倾向于认为,在较新的 CPU 上,任何 级别的操作系统安全性都会尽最大努力确保不会发生这种情况。这当然是可行的,但在现实世界的发行版中使用会很痛苦(我希望)
  • (也就是说,您可能会看看glibcld-linux 实际上做了什么,因为这是它对普通的磁盘可执行文件所做的。它并不漂亮...... )
  • @BRPocock:实际上是it's done very often

标签: c++ c linux memory


【解决方案1】:

简短回答:不。

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

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

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

尝试将fmemopenfilenofexecve 组合使用可能很诱人,但这不起作用有两个原因:

  1. 来自fexecve()手册页:

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

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

  2. 来自fmemopen() manpage:

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

【讨论】:

  • 感谢您的回复;这正是我想要的。谷歌搜索这个主题并没有让我走得太远,我需要满足我的好奇心!
  • 请注意,如今将tmpfs 挂载到/dev/shm/ 已成为一种标准。
  • 现在可以使用 memfd_create() 和 fexecve() 运行内存中的可执行文件。见unix.stackexchange.com/questions/230472/…
【解决方案2】:

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

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

  • 您必须知道可执行文件的大小
  • 在您的 tmpfs 上创建一个文件
  • 使用ftruncate将其缩放到该大小
  • 使用mmap将该文件“映射”到内存中以获得缓冲区的地址
  • 将该地址直接传递给recv 调用以将数据写入到位
  • munmap文件
  • 用文件调用exec
  • rm 文件。即使可执行文件仍在运行也可以完成

【讨论】:

  • 老实说,tmpfs 不会比本地文件系统快,除非您的存储已经满负荷。写入被缓冲到内存中,以便立即执行 execve() 将它们简单地映射出缓存。您支付的唯一成本是最终刷新到磁盘,这是异步的。
  • @AndyRoss,不要为这种事情使用缓冲写入,我会更新我的答案。
  • 即使这样只是避免了内存复制。这里的性能限制是什么?我无法想象通过文件系统的写入速度受到限制但通过网络接收数据包的速度不受限制的情况。似乎非常复杂。只需打开/写入您的常规文件系统并省去麻烦。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-09
    • 2018-07-15
    • 1970-01-01
    • 2016-08-11
    • 1970-01-01
    • 1970-01-01
    • 2013-05-16
    • 1970-01-01
    相关资源
    最近更新 更多