linux系统编程--内存管理
1.进程并不能直接在物理内存上寻址,而是由linux内核为每个进程维护一个特殊的虚拟地址空间。虚拟空间由许多页组成,典型的页大小包括4K(32位系统)和8K(64位系统)。每个页面只有无效和有效这两种状态。 有效页面:和一个物理页或者一些二级存储介质(交换分区或硬盘上文件)相关联。 无效页面:没有关联,代表它没有被分配或者使用。 段错误:对无效页面的访问。 页错误:进程访问一个处在二级存储中的页 2.共享和写时复制: 在不同进程的虚拟空间中的多个页面有可能被映射到同一个物理页面。当一个进程写某个共享的物理页时,可能发生两种情况之一:第一种,内核允许这个操作,并提供在某种程度上的合作和同步机制;第二种,内核会透明的创造一份这个页的拷贝供给该进程进行写操作,这种方式称为写时拷贝。 3.存储器区域 内核将具有某些相同特征的页组成块,这些块叫做存储器区域,段或者映射。下面是存储器区域的分类: 文本段:包含进程代码,字符串,常量和只读数据。 堆栈段:包括进程的执行栈,执行栈包括程序的局部变量和函数返回值。 数据段(堆):包含一个进程的动态存储空间,由malloc分配 BSS段:包含了没被初始化的全局变量 4.动态分配内存 字节单位分配:malloc() 数组分配:calloc(),将分配区域初始化为0,相当于malloc+memset 调整已经分配内存的大小:realloc(),申请一块更大的空间,将原先数据拷贝过去,再释放旧空间 释放空间:free() 5.数据对齐:http://www.cnblogs.com/bakari/archive/2012/08/27/2658956.html 大多情况下,编译器会自动处理对齐问题,malloc,calloc和realloc都是返回对齐的地址 posix_memalign():对于更大块的内存,比如页,需要对齐。即malloc无法满足对齐要求的时候才用 6.glibc内存分配原理: 较小的内存分配:采用伙伴内存分配算法,将数据段分为一系列大小为2的幂的块,返回最小的符合要求的那个块来满足要求,释放则是简单的将这块区域标记为未使用。如果相邻分区都是空闲的,他们会被合成一个更大的分区。 对于较大的内存分配:glibc并不使用堆而是创建一个匿名的内存映射。当程序不再需要这块内存,只需要撤销映射,这块内存就返还给系统了 上面两者的临界点是128K 7.设置存储器分配的参数,比如控制分配临界点的值 mallopt() 查询已分配的内存大小:malloc_usable_size() 强制glibc归还所有可以释放的动态内存给内核:malloc_trim() 查看glibc的内存统计数据:mallinfo() 将内存相关的统计数据打印到标准错误输出:malloc_stats() 8.栈空间动态分配: alloca() 无需释放 strdupa():将一个给定的字符串复制到栈中内存 strndupa():拷贝字符串n个字符到栈内存中 9.字节比较 memcmp() 比较两块内存是否相同 10.字节移动 memmove() 复制前n个字节到dst,可以安全的处理内存重叠区域 memcpy() 不处理内存重叠,重叠了会返回未被定义 memccpy() 遇到重叠会停止拷贝 mempcpy() 遇到重叠会跨过 11.字节搜索:在内存块搜索一个给定的字节 memchr() memrchr() memmem() 12.字节加密 memfrob() 13.锁定部分内存地址 mlock() 锁定全部 mlockall() 解锁:munlock() munlockall() 14.查看页是否在物理内存还是被交换到硬盘 mincore()