创作人QQ:851301776,邮箱:[email protected],欢迎大家一起技术交流,本博客主要是自己学习的心得体会,只为每天进步一点点!
个人座右铭:
1.没有横空出世,只要厚积一定发。
2.你可以学历不高,你可以不上学,但你不能不学习
一、问题
假如动态库中有一个全局变量,动态库所提供的调用函数,本质是操作这个全局变量。如果多个进程同时调用调用这个动态库,可不可以,是不是安全的。
我回答的是:可以。
接下来就会问:为什么?
然后我懵逼了。
唉,被问到几次,一直没实际测试做总结,今天自己总结一下,希望自己可以真正意义上的理解。
二、实战
1.做一个动态库(libhello.so)
(1)头文件内容
#ifndef __HELLO_H__
#define __HELLO_H__
int hello_add();
#endif
(2)源文件中内容
#include <stdio.h>
#include "hello.h"
int num = 0;
int hello_add()
{
printf("num=%d\n", num++);
return 0;
}
2.写两个进程
(1)进程1内容
#include <stdio.h>
#include "./so/hello.h"
int main(void)
{
int i = 100;
while(i--)
{
sleep(1);
printf("%s %d %s\n", __FILE__, __LINE__, __func__);
hello_add();
}
}
(2)进程2内容
#include <stdio.h>
#include "../so/hello.h"
int main(void)
{
int i = 100;
while(i--)
{
sleep(1);
printf("%s %d %s\n", __FILE__, __LINE__, __func__);
hello_add();
}
}
3.打印结果
4.结论
多个进程同时访问同一个动态库,操作的是全局变量,互相不影响。
三、原因
解释:dll是windows中的动态库
当这个访问了的动态链接库的进程被加载时,系统会为这个进程分配4GB的私有地址空间(如果是32位机的话),然后系统就会分析这个可执行模块,找到这个可执行模块中将所要调用的DLL,然后系统就负责搜索这些DLL找到这些DLL后便将这些DLL加载到内存中,并为他们分配虚拟内存空间,最后将DLL的页面映射到调用进程的地址空间汇总,DLL的虚拟内存有代码页和数据页,他们被分别映射到进程A的代码页面和数据页面,如果这时进程B也启动了,并且进程B也许要访问该DLL,这时,只需要将该DLL在虚拟内存中的代码页面和数据页面映射到第二个进程的地址空间即可。其中不变的代码段和数据段只有一份拷贝,会变的内容是各个进程自己拷贝的那一份。
四、动态库和静态库的区别
静态库:使用静态库链接生成的可执行文件,是将静态库中被使用到的模块复制到可执行文件中.
所以,这样的可执行文件不再依赖于静态库文件
动态库:代码加载到内存执行的时候,才发生的链接.延迟链接,也叫按需加载 ,程序执行的过程中,需要使用到动态库的时候,再向系统申请将动态库加载到内存中。
五、进程的内存管理
每个进程都有如下几个段:
(1)代码段:只读可执行
(2)数据段:可读可写,不可执行,主要存放以初始化的全局变量和static声明的变量
(3)栈段:可读可写,不可执行,一个栈段包含多个栈帧.每个函数都有自己对应的栈帧.函数执行期间,函数的栈帧存在,函数调用结束,函数对应的栈帧也就消失了.栈段的生命周期是整个进程 进程的生命周期。
(4)堆段:可读可写,不可执行
(5)BSS段:可读,主要存放未初始化的全局变量和初始化为0的全局变量