背景
Linux可执行程序文件空间布局
查看文件结构命令 size + 可执行文件名
size - list section sizes and total size.
The GNU size utility lists the section sizes---and the total size---for each of the
object or archive files objfile in its argument list. By default, one line of output
is generated for each object file or each module in an archive.
objfile... are the object files to be examined. If none are specified, the file
"a.out" will be used.
[liu@localhost 02]$ ls
env env.c getenv getenv.c orphan orphan.c
[liu@localhost 02]$ size env
text data bss dec hex filename
1195 252 12 1459 5b3 env
[liu@localhost 02]$
关于Linux进程空间结构
在进程第一篇博客提到:fork()会创建一个子进程,会复制父进程的所有资源,但是会拥有和父进程相独立的数据资源与代码区关于fork创建独立空间,以及程序证明的例子
既然创建了独立空间,那么来探究一下对于同一变量在父进程与子进程的地址显示为多少?
#include
#include
int _val = 100;
int main(void)
{
pid_t pid = fork();
if(pid < 0)
perror("fork : "),
exit(0);
else if(pid == 0)
{
printf("this is child _val : %d and it's addr : %p\n", _val, &_val);
}
else
{
printf("this is parent _val : %d and it's addr : %p\n", _val, &_val);
}
return 0;
}
输出结果 :
[liu@localhost jcaddr]$ ./addr
this is parent _val : 100 and it's addr : 0x80497b4
this is child _val : 100 and it's addr : 0x80497b4
改变一下:
[liu@localhost jcaddr]$ cat addr.c
#include
#include
int _val = 100;
int main(void)
{
pid_t pid = fork();
if(pid < 0)
perror("fork : "),
exit(0);
else if(pid == 0)
{
_val = 200;
printf("this is child _val : %d and it's addr : %p\n", _val, &_val);
}
else
{
_val = 50;
printf("this is parent _val : %d and it's addr : %p\n", _val, &_val);
}
return 0;
}
输出结果
[liu@localhost jcaddr]$ ./addr
this is parent _val : 50 and it's addr : 0x80497c4
this is child _val : 200 and it's addr : 0x80497c4
发现进程之间的变量确实是空间独立的,但是这两个进程的变量却是一样的。这样就引出了虚拟内存的概念。
早期的内存分派方式
缺点:降低了效率,处理速度慢,难维护,产生了很多不必要的内存浪费。
分段
1.在编码的过程中,只要指名了所属段,代码和数据段中出现的所有地址都从0x00000000开始,映射关系完全由操作系统维护。
2.cpu将内存分割位不同的段,于是指令和数据的有效地址斌不是真正的物理地址二十相对于段首地址的偏移地址。
缺点:
分段+虚拟地址空间
PCB中的一部分信息就是保存程序的地址空间(mm_struct),同过页表的映射到具体的物理空间,期间程序在物理内存被分段加载内存。
关于虚拟内存大小:
·在mm_struct上,都显示为物理内存的大小,这一点可以想到网盘的1T容可能人们单独用不了1T,所以一百个人可能硬盘10T就ok
关于Linux下的写时拷贝思想
·在fork创建子进程时,子进程复制整个父进程的PCB,包括页表在内,在对子进程中的数据进行操作的时候,页表才开辟新的物理内存,这一点可以类比C++中的写时拷贝
关于页表
·页表既可以将虚拟内存映射到物理内存,也维护着许多,包含有访问权限等等许多内容