C、C++:共享库:是单个函数还是完整的库加载到内存中?
通过静态编译,只有程序实际需要的库函数才链接到程序。共享库怎么样?动态链接器仅将程序实际需要的函数加载到内存中,还是始终加载全部共享库?如果它是函数,我如何获得程序的实际大小,包括运行时加载的函数?
谢谢 ! 奥利弗
With static compilation, only the functions of a library which are actually needed by a program are linked to the program. How is that with shared libraries ? Are only the functions actually needed by a program are loaded into memory by the dynamic linker, or is always the total shared library loaded ? If it is functions, how could I get the actual size of a program including its loaded functions during runtime ?
Thank You !
Oliver
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
通过静态编译,只有程序实际需要的库函数才会链接到程序。共享库怎么样?
程序以符号方式引用共享库,也就是说,程序将通过名称来标识与其链接的共享库。
动态链接器仅将程序实际需要的函数加载到内存中,还是始终加载整个共享库?
程序将引用共享库中的特定入口点和数据对象。共享库将作为单个大对象映射到内存中,但内核只会对实际引用的页面进行分页。加载的库的总量将取决于引用的密度、链接到它的其他图像的引用以及库自身功能的位置。
如果是函数,我怎样才能获得程序的实际大小,包括运行时加载的函数?
在 Mac 和其他基于 Unix 的系统上最好的方法是使用 ps(1)< /强>。
With static compilation, only the functions of a library which are actually needed by a program are linked to the program. How is that with shared libraries ?
Shared libraries are referenced by the program symbolically, that is, the program will identify, by name, the shared library it was linked with.
Are only the functions actually needed by a program are loaded into memory by the dynamic linker, or is always the total shared library loaded ?
The program will reference specific entry points and data objects in the shared library. The shared library will be mapped into memory as a single large object, but only the pages that are actually referenced will be paged in by the kernel. The total amount of the library that gets loaded will depend on both the density of references, references by other images linked to it, and by the locality of the library's own functionality.
If it is functions, how could I get the actual size of a program including its loaded functions during runtime ?
The best way on Mac and other Unix-based systems is with ps(1).
当您静态链接时,只有(可能)调用的函数会链接到可执行文件中 - 但在运行时,可执行文件中的数据将通过请求分页读入内存。
创建进程时,地址会分配给该进程的可执行文件和共享库中的所有代码,但文件中的代码/数据当时不一定读入物理内存。当您尝试访问当前不在物理内存中的地址时,它将触发不存在异常。操作系统虚拟内存管理器将对此作出反应,将文件中的页面读取到物理内存中,而不是让访问继续进行。
加载是逐页完成的,这通常意味着一次 4 或 8 KB 的块(例如,x86 使用 4K 页面,Alpha 使用 8k)。 x86 确实还能够创建更大的(4 兆字节)页面,但这些页面(至少通常)不用于普通代码 - 它们用于映射保持(半)永久映射的大内存块,例如作为典型显卡上的内存“窗口”,它也经过映射,因此可以由 CPU 直接访问。
大多数加载器都有一些优化,因此(例如)它们会在程序最初启动时尝试读取更大的内存块。这使得它的启动速度比访问每页代码时出现中断和单独读取的情况更快。该优化的具体细节因操作系统(通常甚至同一操作系统的版本)而异。
When you link statically, only the functions that are (potentially) called get linked into the executable -- but at run-time, the data from the executable file will be read into memory by demand paging.
When the process is created, addresses are assigned to all the code in the executable and shared libraries for that process, but the code/data from the file isn't necessarily read into physical memory at that time. When you attempt to access an address that's not currently in physical memory, it'll trigger a not-present exception. The OS virtual memory manager will react to that by reading the page from the file into physical memory, than letting the access proceed.
The loading is done on a page-by-page basis, which usually means blocks of 4 or 8 kilobytes at a time (e.g., x86 uses 4K pages, Alpha used 8k). x86 does also have an ability to create larger (4 megabyte) pages, but those aren't (at least usually) used for normal code -- they're for mapping big blocks of memory that remain mapped (semi-)permanently, such as the "window" of memory on a typical graphics card that's also mapped so it's directly accessible by he CPU.
Most loaders have some optimizations, so (for example) they'll attempt to read bigger blocks of memory when the program starts up initially. This lets it start faster than if there was an interrupt and separate read for each page of code as it's accessed. The exact details of that optimization vary between OSes (and often even versions of the same OS).