gpt4 book ai didi

c - 当二进制文件运行时,它是否将其整个二进制数据立即复制到内存中?我可以改变吗?

转载 作者:IT王子 更新时间:2023-10-29 00:25:59 26 4
gpt4 key购买 nike

它在执行之前是否将整个二进制文件复制到内存中?我对这个问题很感兴趣,想把它改成其他的方式。我的意思是,如果二进制文件有 100M 大(似乎不可能),我可以在将它复制到内存中时运行它。这可能吗?

或者您能告诉我如何查看它的运行方式吗?我需要哪些工具?

最佳答案

应用程序级程序员的理论模型似乎是这样。事实上,正常的启动过程(至少在 Linux 1.x 中,我相信 2.x 和 3.x 优化但相似)是:

  • 内核创建进程上下文(或多或少,虚拟机)
  • 在该进程上下文中,它定义了一个虚拟内存映射,映射从 RAM 地址到可执行文件的开头
  • 假设您是动态链接的(默认/通常),ld.so 程序(例如 /lib/ld-linux.so.2)定义在你的程序头中,为共享库设置内存映射
  • 内核执行jmp 到您程序的启动例程中(对于C 程序,这是类似于 crtprec80,它调用 main)。由于它只设置了映射,并没有实际加载任何页面(*),这会导致 CPU 的内存管理单元出现页面错误,这是对内核的中断(异常,信号)。
  • 内核的页面错误处理程序加载程序的某些部分,包括部分导致页面错误,进入 RAM。
  • 当你的程序运行时,如果它访问一个没有 RAM 支持的虚拟地址立即启动,将发生页面错误并导致内核暂停程序简而言之,从光盘加载页面,然后将控制权返回给程序。这一切发生在“指令之间”,通常无法检测到。
  • 当您使用 malloc/new 时,内核会创建 RAM 的读写页面(没有磁盘支持文件)并将它们添加到您的虚拟地址空间。<
  • 如果您通过尝试访问一个在虚拟内存映射中设置的内存位置而引发页面错误,您将收到一个分段违规信号 (SIGSEGV),这通常是致命的。
  • 当系统用完物理 RAM 时,RAM 页面将被删除;如果它们是光盘上已有内容的只读副本(如可执行文件或共享对象文件),它们只会被取消分配并从其源重新加载;如果它们是可读写的(比如您使用 malloc“创建”的内存),它们将被写入(页面文件 = 交换文件 = 交换分区 = 磁盘虚拟内存)。访问这些“已释放”的页面会导致另一个页面错误,并重新加载它们。

不过,通常情况下,除非您的进程大于可用 RAM — 并且数据几乎总是比可执行文件大得多 — 您可以安全地假装世界上只有您一个人,并且这些请求分页的事情都没有发生。

因此:实际上,内核已经在加载程序时运行您的程序(如果您从不跳入该代码/引用该数据,甚至可能永远不会加载某些页面)。

如果您的启动特别缓慢,您可以查看 prelink 系统来优化共享库加载。这减少了 ld.so 在启动时必须做的工作量(在程序的 exec 和调用 main 之间,以及就像你第一次调用库例程时一样)。

有时,静态链接可以提高程序的性能,但会以 RAM 为代价——因为你的库不是共享的,除了共享的之外,你还在复制“你的 libc”例如,所有其他程序正在使用的 libc。这通常仅在您的程序或多或少单独在机器上运行的嵌入式系统中有用。

(*) 事实上,内核有点聪明,一般会预加载一些页面减少页面错误的数量,但理论是一样的,不管优化

关于c - 当二进制文件运行时,它是否将其整个二进制数据立即复制到内存中?我可以改变吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8506865/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com