发布网友 发布时间:2022-04-23 00:50
共3个回答
热心网友 时间:2023-07-07 03:37
1、虽然动态库有点浪费内存,但是动态库最大的作用是:减少占用磁盘空间,减少开发时的编译时间,而不是你想的编译速度慢。因为采用了动态库,所以如果我修改了动态库,我只需要编译动态库。而如果采用了静态库,如果修改了静态库,那么,所有用了该静态库的程序和静态库都必须重新编译。而且gcc不是扫描整个libc.so文件。因为so文件里有符号表,哪个符号在哪个.o文件里,只要扫描符号表就知道了,而且由于他不需要从so文件中拷贝使用的函数,从某种意义上来说编译速度比静态库更快。
2、动态库的加载采用写时拷贝技术,即:只有当我用这个函数的时候我才把该函数部分拷贝过来,它不会拷贝整个so文件,只会拷贝需要的部分。
热心网友 时间:2023-07-07 03:37
但是动态库中却包含了大量的函数,假设我只使用了printf函数,但是却加载了整个libc.so.这样不是内存的浪费吗。
libc中的函数都是常用的.而且动态库是所有进程共享的.即使整个库都加载了,你的进程用不到,其他进程还会用到的.
如果某个你自己的动态库只有你自己的进程用,那么我相信你就不会再库中编译很多你用不到的函数来浪费内存了.
一个动态库文件不仅包含真正需要拷贝到内存中的机器码,还包含一些其他的信息.比如函数索引.
另外gcc编译的时候只会扫描库的索引,而不是去扫描整个库文件.
热心网友 时间:2023-07-07 03:38
动态库的作用:
节省磁盘和内存空间,还可以减少物理内存页面的换入换出,也可以增加CPU缓存的命中率;
程序的升级变得更加容易;
便于不同的开发者和开发组织之间进行开发和测试;
至于你的疑问:
1. 只使用printf函数,系统只会加载libc.so的printf所在的页;所以操作系统管理内存是按照页来管理的,操作系统为进程建立内存和虚拟空间的映射,以及虚拟地址空间和磁盘文件(可执行程序)的映射,并且操作系统提供了写时拷贝技术;也就是只有真正运行了printf函数时,操作系统才将libc.so中的printf函数所在的页加载到内存(通过以上两个映射来做)
所以不存在你的内存浪费的问题;
2. 使用printf函数,在编译时,这里需要扫面整个libc.so,静态库也一样;
链接时,可执行程序只保存了printf符号(PIC,地址无关代码),和libc.so库名称;
运行时,动态加载器需要遍历可执行程序所使用的所有地址无关代码,并且记载所有的so库(加载到进程虚拟地址空间,实际上还没有加载到内存),将printf与实际的so库虚拟地址关联;
这里当程序运行printf时,需要进行间接地址访问到so库的地址,所以效率上比静态库低(静态库是直接地址访问)
并且,由于动态库需要动态加载器的加载过程,而静态库不需要,所以运行效率没有静态库方式高;
希望以上的解答可以给你帮助。另外,如果你还有其他疑惑,你可以去看下《程序员的自我修养》这本书,里面讲的比较详细。
如果你有其他疑问,尽快在这里问,我懂的话,都可以给你解答
参考资料:《程序员的自我修养》