【读书笔记】程序员的自我修养总结(七)

【读书笔记】程序员的自我修养总结(七)

标签: 【编程开发】

声明:引用请注明出处

说明:这是程序员的自我修养一书的读书总结,随着阅读的推进,逐步增加内容。 本文主要介绍可执行文件的装载与进程

ELF文件的链接视图和执行视图

当段的数量增多时,会产生空间浪费的问题:因为ELF文件被映射时时以系统的页长度作为单位的,那么每个段在影射时的长度应该都是系统页长度的整数倍,如果不是,那么多余部分将占用一个页,而一个ELF文件中往往有十几个段,那么内存空间将噪声浪费。

解决方法: 操作系统在装载可执行文件时,可以发现主要关心的是段的权限(可读,可写,可执行)等。比如:

所以,可以将相同权限的段,合并到一起当作一个段进行映射,可以明显减少页面内部碎片,节省内存空间。在目标文件链接为可执行文件时,链接器会尽量将相同权限属性的段分配在同一空间。被称为Segment。 所以,会有ELF文件会有链接视图和执行视图的概念,链接视图以section,而执行视图为Segment,两者区别就是相同特性之间的段之间的合并。

堆和栈

堆(heap)和栈(stack)在进程的虚拟空间中的表现也是以VMA的形式存在的。C语言中最常用的malloc就是从堆中分配的,堆由系统库管理。栈一般也叫做堆栈,每个线程都有自己的堆栈,对于单线程程序来讲,这个VMA堆栈全归它使用。那么一个进程基本上可以分为如下几种VMA区域:

堆的最大申请数量

Linux下虚拟地址空间分给进程本身的是3GB,windows大概是默认2GB。可以测试一下malloc函数进行地址空间的申请,到底能申请多大内存?

#include<stdio.h>#include<stdlib.h>unsigned maximum = 0;int main(){unsigned blocksize[] = {1024 * 1024, 1024, 1};int i, count;for(i = 1; i < 3; i++)for(count = 1; ; count++){void *block = malloc(maximum + blocksize[i] * count);if(block){maximum = maximum + blocksize[i] * count;free(block);}else{break;}}printf(“maximum malloc size = %u bytes\n”, maximum);}

经测试,得到的输出为:

maximum malloc size = 1826488009 bytes

大约是1.7GB左右。

段地址对齐

要映射一段物理内存和进程虚拟地址空间之间建立映射关系,这段内存空间的长度必须是4096的整数倍,并且这段空间在物理内存和进程虚拟地址空间中的起始地址必须是4096的整数倍。最简单的方法就是每个段分开映射,不足一个页的占据一个页,这样当然会造成内部碎片。而有些UNIX采用各个段接壤部分共享一个物理页面,然后将该物理页面分别映射两次。

进程栈初始化

进程刚开始启动的时候,须知道一些进程运行的环境,最基本的就是系统环境变量和进程的运行参数。很常见的做法是操作系统在进程启动前将这些信息提前保存到进程的虚拟空间的栈中。 进程在启动以后,,程序的库部分会把堆栈里的初始化信息中的参数信息传递给main(),也就是main函数中的两个argc和argv两个参数,分别对应命令行中参数数量和命令行参数字符串指针数组。

2015-11-01读书笔记 张朋艺

送给中意的TA,背面写上:某年某月某日,

【读书笔记】程序员的自我修养总结(七)

相关文章:

你感兴趣的文章:

标签云: