《Linux/Unix系统编程手册》读书笔记4

王朝学院·作者佚名  2016-05-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

《linux/Unix系统编程手册》读书笔记4《Linux/Unix系统编程手册》读书笔记 目录

第7章:

内存分配

通过增加堆的大小分配内存,通过提升PRogram break位置的高度来分配内存。

基本学过C语言的都用过malloc来分配内存,而malloc都基于brk()和sbrk()。

1 #include <unistd.h>2 3 int brk(void *end_data_segment);4 5 int *sbrk(intptr_t increment);

brk()系统调用会将program break设置为end_data_segment的位置。成功调用返回0,失败返回-1。

sbrk()系统调用会将program break原来的位置增加increment的大小。成功调用返回原来program break的位置,失败返回(void *)-1。

PS:sbrk(0)返回program break的当前位置。

malloc()函数,C使用该函数在堆上分配和释放内存。

1 #include <stdlib.h>2 3 void *malloc(size_t size);

malloc分配size字节大小的内存。并返回指向新分配的内存的起始位置的指针,该内存未经初始化;失败返回NULL。

通常对返回的指针进行显式类型转换来获得自己想要的类型的指针。

实际上每次调用malloc分配内存时,会额外分配多几个字节来记录这块内存的大小。(如下图所示)

free()函数用来释放内存块。

1 #include <stdlib.h>2 3 void free(void *ptr);

free释放ptr指向的内存块,ptr必须是malloc、calloc、realloc返回的指针。

free不会降低program break的位置,而是将该内存添加到空闲内存列表,用于以后malloc使用。

PS:不能对已经调用过free函数的指针,再次调用free,这样会产生错误。

因为malloc分配后的内存会有内存块的长度,所以free会知道这块内存的大小,从而准确的将内存块释放,并放入空闲内存块列表中。

PS:因此不能用free随便释放不是malloc返回的指针。

经过free释放后的内存块结构如下:

其实malloc调用是先查找空闲内存块列表,找到合适的内存块。如果找不到合适的内存块就调用sbrk()来分配更多的内存,为了减少调用sbrk的次数,会分配比size大小更多的内存来增加program break的位置,超出size大小的内存块会放到空闲内存列表。

calloc()函数可以对一组相同的对象分配内存。

#include <stdlib.h>void *calloc(size_t numitems, size_t size);

numitems指定了对象的数量,size指定了每个对象的大小。成功调用返回内存块的起始地址,失败返回NULL。malloc返回的内存不会初始化,而calloc返回的内存块是已初始化。

realloc()函数可以调整一块内存的大小。

1 #include <stdlib.h>2 3 void *realloc(void *ptr, size_t size);

ptr是需要调整大小的内存块的指针, size是所需调整大小的期望值。

成功调用会返回指向调整后内存块的指针(位置可能不同),失败返回NULL。

练习:

7-1. 修改程序清单7-1中的程序,在每次执行malloc()后打印出program break的当前至。指定一个较小的内存分配尺寸来运行该程序。这将证明malloc不会在每次调用时都会调用sbrk()来调整program break的位置,而是周期性地分大块内存,并从中将小片内存返回给调用者。

程序清单7-1:

1 /* 2 * ===================================================================================== 3 * 4 * Filename: free_and_sbrk.c 5 * 6 * Description: 7 * 8 * Version: 1.0 9 * Created: 2014年03月19日 11时37分09秒10 * Revision: none11 * Compiler: gcc12 *13 * Author: alan (), alan19920626@Gmail.com14 * Organization: 15 *16 * =====================================================================================17 */18 19 #include "tlpi_hdr.h"20 21 #define MAX_ALLOCS 100000022 23 int main(int argc, char *argv[]){24 char *ptr[MAX_ALLOCS];25 int freeStep, freeMin, freeMax, blockSize, numAllocs, j;26 27 printf("\n");28 29 if(argc < 3 || strcmp(argv[1], "--help") == 0)30 usageErr("%s num-allocs blocksize [step [min [max]]]\n", argv[0]);31 32 numAllocs = getInt(argv[1], GN_GT_0, "num-allocs");33 34 if(numAllocs > MAX_ALLOCS)35 cmdLineErr("num-allocs > %d\n", MAX_ALLOCS);36 37 blockSize = getInt(argv[2], GN_GT_0 | GN_ANY_BASE, "blocksize");38 39 freeStep = (argc > 3) ? getInt(argv[3], GN_GT_0, "step") : 1;40 freeMin = (argc > 4) ? getInt(argv[4], GN_GT_0, "min") : 1;41 freeMax = (argc > 5) ? getInt(argv[5], GN_GT_0, "max") : numAllocs;42 43 if(freeMax > numAllocs)44 cmdLineErr("free-max > num-allocs\n");45 46 printf("Initial program break: %10p\n", sbrk(0));47 48 printf("Allocing %d*%d bytes\n", numAllocs, blockSize);49 50 for(j = 0; j < numAllocs; j++){51 ptr[j] = malloc(blockSize);52 if(ptr[j] == NULL)53 errExit("malloc");54 }55 56 printf("Program break is now: %10p\n", sbrk(0));57 58 printf("Freeing blocks from %d to %d in steps of %d\n", freeMin, freeMax, freeStep);59 for(j = freeMin-1; j < freeMax; j += freeStep)60 free(ptr[j]);61 62 printf("After free(), program break is %10p\n", sbrk(0));63 64 exit(EXIT_SUCCESS);65 }

View Code 1 /* 2 * ===================================================================================== 3 * 4 * Filename: free_and_sbrk.c 5 * 6 * Description: 7 * 8 * Version: 1.0 9 * Created: 2014年03月19日 11时37分09秒10 * Revision: none11 * Compiler: gcc12 *13 * Author: alan (), alan19920626@gmail.com14 * Organization: 15 *16 * =====================================================================================17 */18 19 #include "tlpi_hdr.h"20 21 #define MAX_ALLOCS 100000022 23 int main(int argc, char *argv[]){24 char *ptr[MAX_ALLOCS];25 int freeStep, freeMin, freeMax, blockSize, numAllocs, j;26 27 printf("\n");28 29 if(argc < 3 || strcmp(argv[1], "--help") == 0)30 usageErr("%s num-allocs blocksize [step [min [max]]]\n", argv[0]);31 32 numAllocs = getInt(argv[1], GN_GT_0, "num-allocs");33 34 if(numAllocs > MAX_ALLOCS)35 cmdLineErr("num-allocs > %d\n", MAX_ALLOCS);36 37 blockSize = getInt(argv[2], GN_GT_0 | GN_ANY_BASE, "blocksize");38 39 freeStep = (argc > 3) ? getInt(argv[3], GN_GT_0, "step") : 1;40 freeMin = (argc > 4) ? getInt(argv[4], GN_GT_0, "min") : 1;41 freeMax = (argc > 5) ? getInt(argv[5], GN_GT_0, "max") : numAllocs;42 43 if(freeMax > numAllocs)44 cmdLineErr("free-max > num-allocs\n");45 46 printf("Initial program break: %10p\n", sbrk(0));47 48 printf("Allocing %d*%d bytes\n", numAllocs, blockSize);49 50 for(j = 0; j < numAllocs; j++){51 ptr[j] = malloc(blockSize);52 if(ptr[j] == NULL)53 errExit("malloc");54 printf("After malloc(), program break is: %10p\n", sbrk(0));55 }56 57 printf("Program break is now: %10p\n", sbrk(0));58 59 printf("Freeing blocks from %d to %d in steps of %d\n", freeMin, freeMax, freeStep);60 for(j = freeMin-1; j < freeMax; j += freeStep)61 free(ptr[j]);62 63 printf("After free(), program break is %10p\n", sbrk(0));64 65 exit(EXIT_SUCCESS);66 }

测试结果:

lancelot@debian:~/Code/tlpi$ ./7-1 15 10 2Initial program break: 0x1913000Allocing 15*10 bytesAfter malloc(), program break is: 0x1934000After malloc(), program break is: 0x1934000After malloc(), program break is: 0x1934000After malloc(), program break is: 0x1934000After malloc(), program break is: 0x1934000After malloc(), program break is: 0x1934000After malloc(), program break is: 0x1934000After malloc(), program break is: 0x1934000After malloc(), program break is: 0x1934000After malloc(), program break is: 0x1934000After malloc(), program break is: 0x1934000After malloc(), program break is: 0x1934000After malloc(), program break is: 0x1934000After malloc(), program break is: 0x1934000After malloc(), program break is: 0x1934000Program break is now: 0x1934000Freeing blocks from 1 to 15 in steps of 2After free(), program break is 0x1934000

可以清楚的看得出来,内存块只是调用了一次sbrk()来改变program break的位置,分配15块10个字节的内存块,只是第一次的时候调用了sbrk分配了1000个字节的内存块,并将990个字节大小的内存块放到空闲内存块列表,供以后malloc的调用使用。。。。

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航