linux系统编程读书笔记 第八章 (续)

来源:互联网 发布:mac keynote 免费模板 编辑:程序博客网 时间:2024/05/16 12:37

       calloc与malloc的区别在于calloc会给分配的区域以0来初始化,这个函数的速度比memset还快,那要memset来干嘛?

       realloc是重新分配某块内存的大小,如果realloc不能在已有空间上增加到size大小,那么就会重新申请一块size大小的空间,将原本的数据拷贝到新空间中,然后将旧的空间释放。因为有潜在的拷贝操作,所以一个扩大原区域的realloc()操作可能是相当耗时的。当失败的时候realloc返回NULL并设置errno为ENOMEM。这时ptr指向的内存区域没有改变。

       另外补充一个基本概念 进程地址空间是什么东西? http://msdn.microsoft.com/zh-cn/library/ms189334(v=sql.105).aspx

       还有http://soft.chinabyte.com/os/51/12324551.shtml

       释放内存用的是free,不使用的话会产生内存泄露、释放后再使用的问题。

       计算机在数据对齐这方面有着很严格的要求,假如不对齐会导致错误或者性能下降,大多数情况下,编译器和C库是会自动对齐的。Posix提供了一个叫做posix_memalign()的函数来完成对齐的功能。对于非标准类型的对齐,有四条有用的规则:

1.   一个结构的对齐要求和它的成员中最大的那个类型是一样的。

2.   结构体也引入了对填充的需求,以此来保证每一个成员都符合各自的对齐要求

3.   一个联合的对齐和联合里最大的类型一致。

4.   一个数组的对齐和数组里的元素类型一致。

       假设一个指针从一个较少字节对齐的类型强转为一个较多字节对齐的类型时,当通过这样的指针来访问时,会导致处理器不能对较多字节类型的数据正确对齐。这样写代码产生的问题是什么?

       接下来是伙伴系统、内碎片、外碎片的概念了。

       一个内存的分配“栓”住另外一个内存是什么情况?中断点?

       Glibc并不是一直在试图将空间返回给系统。只有当堆明显的大于已分配的内存时,glibc才会减小堆的大小。

       匿名存储器映射和基于文件的映射很相似,只是不基于文件,所以称之为“匿名”。实际上,一个匿名内存映射只是一块已经用0初始化的大的内存块,以供用户使用。

       使用匿名映射的好处:无需关心碎片;匿名存储映射的大小是可以调整的;每个分配存在于独立的内存映射;每个存储器映射都是页面大小的整数倍;创建一个新的内存映射比从堆中返回内存的负载要大。

       综上,小块内存分配用malloc,大块用匿名内存映射。mmap()用来创建内存映射,munmap()用来销毁。

       mallopt()是用来修改内核分配操作的参数的,可以修改的包括环境变量MALLOC_CHECK_的值等。

       以下两个是用来控制内存分配的底层函数,高级货:malloc_usable_size()和malloc_trim()。第一个调用成功时返回ptr指向的动态内存块的实际大小,第二个函数允许程序强制归还所有可释放的动态内存给内核。调用malloc_trim()成功时,数据段会尽可能地收缩,但是填充字节被保留下来(填充字节是什么?)。

       MALLOC_CHECK_环境变量可以设置来开启存储系统额外的调试功能。这个额外的调试会降低内存分配的效率,然而这个开销在开发应用的调试阶段却是非常值得的,因为仅仅一个变量就能控制调试,而不必重新编译程序。

       如命令    MALLOC_CHECK_=1./rudder

       如果设置为0,存储系统会忽略所有错误;如果设为1,信息会被输出到标准错误输出stderr;如果设置为2,进程会立即通过abort()终止。

       mallinfo()函数可以用来获得关于动态存储分配系统的统计数据,这个函数返回mallinfo结构体,里面包括了一些数据如空闲块个数,匿名映射个数等信息。

       另外还有stats()函数,将跟内存相关的统计数据打印到标准错误输出。

       前面的动态内存分配是用堆来分配的,而通过alloca()可以实现用栈来分配内存。分配好后,当调用函数返回时,这块内存将被自动释放。

       不能用alloca()得到的内存来作为一个函数调用的参数,因为分配到的内存块会被当做参数保存在函数的栈中。(此话怎解?)

       因为alloca的表现不太好,所以当要考虑代码的可移植性和跨平台性时,不建议使用。

       函数alloca通常用来临时复制一个字符串或者申请变长数组。

       像memset这些字节设置、比较、移动等操作的函数,是不会返回错误信息的,因此防范错误是程序员的职责,如果传递错误的内存区域作参数的话,你将毫无疑问的得到段错误。

       可以使用calloc()分配内存那就坚决不要使用memset()!

       通过mlock()可以将页面锁定到物理内存,来保证它们不会被交换到磁盘。

       通过mlockall()函数锁定一个进程在现有地址空间在物理内存中的所有页面。

       解锁则通过munlock()和munlockall()。

       mincore()函数可以用来确定一个给定范围的内存是在物理内存中还是交换到了硬盘中。
原创粉丝点击