本文摘自:http://blog.csdn.net/liuchao1986105/article/details/6677663
1、内核分配物理内存的最小单位为一个物理页面,一个物理页面为4kb。无论虚拟内存分配了多少字节,比如malloc(400),内核仍然分配4kb物理内存页面。
2、malloc语句执行时,只是给进程分配了虚拟内存,虚拟内存此时不占用物理内存。当使用此处内存时,比如变量赋值*p = ??或memcpy或strcpy时,内核会产生一个页故障,从而为进程分配一个物理页面。
3、进程状态可以在/proc中根据pid值找到进程的目录。 目录中statm信息(cat statm)中的7个数,以页为单位。 从左至右依次为size:任务虚拟地址空间大小。 resident:应用程序正在使用的物理内存大小。 shared:共享页数。
trs:程序所拥有的可执行虚拟内存大小。 lrs:被映像到任务的虚拟内存空间的库的大小。 drs:程序数据段和用户态的栈的大小。 dt:脏页数量。
4、目录中maps信息(cat maps)中,表示进程使用的虚拟地址(栈,堆,代码等)。 内存使用权限信息r=读,w=写,x=执行,s=共享,p=私有。 r-xp通常表示代码段,只读,可执行。Rw-p通常表示数据段,可读写,不能执行。 rwxp通常表示栈段,读写,可执行。栈不仅可以保存数据,也可以保存代码。
5、32位操作系统中,进程虚拟内存为4g,分为两部分,内核空间(高1g),用户空间(低3g)。
6、堆段:每个进程有一个,不论是主进程、动态库还是不同的线程里申请的堆内存,都反映在进程的堆段。 栈段:每个线程有一个,如果进程中有多个线程,则包含多个栈段。 代码段:由于其只读,不会被修改,故其在整个系统中共享。比如说一个执行文件,在系统中同时存在多个进程,那么这些进程将共享其代码段所占用的内存。
数据段:由于它是可写的,其内容与其所在的进程高度相关,所以在程序运行时会为每个进程创建一个数据段副本,故每个进程有一个数据段。
7、p = malloc(xxx); 分配给p的大小存放于*(p - 4)位置。
8、readelf、size、strip命令的使用。Nm ???.out检查???.out执行文件的符号表。
9、检查当前内核配置的进程栈大小,使用ulimit -a命令查看stack size:。 如需设置栈大小,使用ulimit -s 16384,栈大小为16k。
10、线程栈空间未设置时,通常为2m。2m的栈空间略微显得太大。所以有必要修改线程栈空间大小。 设置方法为: pthread_attr_t tattr; pthread_attr_init(&tattr); pthread_attr_setstacksize(&tattr,
--SIZE--); /* --SIZE-- 为设置的值,可以写8k等。*/ pthread_create(&tid, &tattr, start_routine, arg); /* 以tattr为属性创建线程 */
11、进程启动前加载过多的动态库会影响进程启动速度。静态库编译进入进程时,其查找静态库中的函数时仅偏移计算一次即可调用静态库中的函数。 进程调用动态库中函数时,进程将处理权交给linker,由于linker也不知道调用的函数是在哪个动态库,所以它将在整个执行文件和动态库的范围内查找。这种查找是符号表字符串的查找比较,效率较为低下,间接影响了进程的启动速度或执行速度。
12、善用查表法(数组)优化查找效率。
13、对于if中的逻辑连接运算符,尽量将计算速度最快的条件放在运算符左边。例如if((b == 0) || (TURE == func(a, b)))。同理,概率大的条件,也尽量放在左边。
14、利用现代cpu乱序执行的特点,将访问内存的语句置入代码块前端,其后代码为访问cache,所以可以在cpu等待访问内存的时间利用在计算访问cache的语句,达到看似无缝内存访问时延的指令执行。