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

第7章:

内存分配

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

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

 #include <unistd.h>

 int brk(void *end_data_segment);

 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使用该函数在堆上分配和释放内存。

 #include <stdlib.h>

 void *malloc(size_t size);

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

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

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

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

 #include <stdlib.h>

 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()函数可以调整一块内存的大小。

 #include <stdlib.h>

 void *realloc(void *ptr, size_t size);

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

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

练习:

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

程序清单7-1:

 /*
* =====================================================================================
*
* Filename: free_and_sbrk.c
*
* Description:
*
* Version: 1.0
* Created: 2014年03月19日 11时37分09秒
* Revision: none
* Compiler: gcc
*
* Author: alan (), alan19920626@gmail.com
* Organization:
*
* =====================================================================================
*/ #include "tlpi_hdr.h" #define MAX_ALLOCS 1000000 int main(int argc, char *argv[]){
char *ptr[MAX_ALLOCS];
int freeStep, freeMin, freeMax, blockSize, numAllocs, j; printf("\n"); if(argc < || strcmp(argv[], "--help") == )
usageErr("%s num-allocs blocksize [step [min [max]]]\n", argv[]); numAllocs = getInt(argv[], GN_GT_0, "num-allocs"); if(numAllocs > MAX_ALLOCS)
cmdLineErr("num-allocs > %d\n", MAX_ALLOCS); blockSize = getInt(argv[], GN_GT_0 | GN_ANY_BASE, "blocksize"); freeStep = (argc > ) ? getInt(argv[], GN_GT_0, "step") : ;
freeMin = (argc > ) ? getInt(argv[], GN_GT_0, "min") : ;
freeMax = (argc > ) ? getInt(argv[], GN_GT_0, "max") : numAllocs; if(freeMax > numAllocs)
cmdLineErr("free-max > num-allocs\n"); printf("Initial program break: %10p\n", sbrk()); printf("Allocing %d*%d bytes\n", numAllocs, blockSize); for(j = ; j < numAllocs; j++){
ptr[j] = malloc(blockSize);
if(ptr[j] == NULL)
errExit("malloc");
} printf("Program break is now: %10p\n", sbrk()); printf("Freeing blocks from %d to %d in steps of %d\n", freeMin, freeMax, freeStep);
for(j = freeMin-; j < freeMax; j += freeStep)
free(ptr[j]); printf("After free(), program break is %10p\n", sbrk()); exit(EXIT_SUCCESS);
}
 /*
* =====================================================================================
*
* Filename: free_and_sbrk.c
*
* Description:
*
* Version: 1.0
* Created: 2014年03月19日 11时37分09秒
* Revision: none
* Compiler: gcc
*
* Author: alan (), alan19920626@gmail.com
* Organization:
*
* =====================================================================================
*/ #include "tlpi_hdr.h" #define MAX_ALLOCS 1000000 int main(int argc, char *argv[]){
char *ptr[MAX_ALLOCS];
int freeStep, freeMin, freeMax, blockSize, numAllocs, j; printf("\n"); if(argc < || strcmp(argv[], "--help") == )
usageErr("%s num-allocs blocksize [step [min [max]]]\n", argv[]); numAllocs = getInt(argv[], GN_GT_0, "num-allocs"); if(numAllocs > MAX_ALLOCS)
cmdLineErr("num-allocs > %d\n", MAX_ALLOCS); blockSize = getInt(argv[], GN_GT_0 | GN_ANY_BASE, "blocksize"); freeStep = (argc > ) ? getInt(argv[], GN_GT_0, "step") : ;
freeMin = (argc > ) ? getInt(argv[], GN_GT_0, "min") : ;
freeMax = (argc > ) ? getInt(argv[], GN_GT_0, "max") : numAllocs; if(freeMax > numAllocs)
cmdLineErr("free-max > num-allocs\n"); printf("Initial program break: %10p\n", sbrk()); printf("Allocing %d*%d bytes\n", numAllocs, blockSize); for(j = ; j < numAllocs; j++){
ptr[j] = malloc(blockSize);
if(ptr[j] == NULL)
errExit("malloc");
printf("After malloc(), program break is: %10p\n", sbrk());
} printf("Program break is now: %10p\n", sbrk()); printf("Freeing blocks from %d to %d in steps of %d\n", freeMin, freeMax, freeStep);
for(j = freeMin-; j < freeMax; j += freeStep)
free(ptr[j]); printf("After free(), program break is %10p\n", sbrk()); exit(EXIT_SUCCESS);
}

测试结果:

lancelot@debian:~/Code/tlpi$ ./-   

Initial program break:           0x1913000
Allocing * bytes
After malloc(), program break is: 0x1934000
After malloc(), program break is: 0x1934000
After malloc(), program break is: 0x1934000
After malloc(), program break is: 0x1934000
After malloc(), program break is: 0x1934000
After malloc(), program break is: 0x1934000
After malloc(), program break is: 0x1934000
After malloc(), program break is: 0x1934000
After malloc(), program break is: 0x1934000
After malloc(), program break is: 0x1934000
After malloc(), program break is: 0x1934000
After malloc(), program break is: 0x1934000
After malloc(), program break is: 0x1934000
After malloc(), program break is: 0x1934000
After malloc(), program break is: 0x1934000
Program break is now: 0x1934000
Freeing blocks from to in steps of
After free(), program break is 0x1934000

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

《Linux/Unix系统编程手册》读书笔记4的更多相关文章

  1. 【鸟哥的Linux私房菜】笔记1

    Linux是什么 从操作系统与cpu架构关系到linux  Richard Mathew Stallman GPL 关于GNU计划 Linux的发展 Linux的核心版本 Linux的特色 Linux ...

  2. 【鸟哥的Linux私房菜】笔记3

    正确地开机 最好不要使用root账号登陆!GNOME图形界面 View items as a list X WindowShell 文本交互界面bash是Shell的名称,Linux的默认壳程序就是b ...

  3. 【鸟哥的Linux私房菜】笔记2

    Linux的应用 学习资源整理 安装记录 >< 1.Linux的应用: 网络服务器 数据库 学术机构的高效运算任务 嵌入式系统 ... 2.挂载与磁盘分区 学习资源整理 学习 1.书上的网 ...

  4. 《鸟哥的Linux私房菜》笔记——02. 关于Linux

    Unix 历史 1969年以前:伟大的梦想--Bell, MIT 与 GE 的「Multics」系统 1969年:Ken Thompson 的小型 file server system 1973年:U ...

  5. 《鸟哥的Linux私房菜》笔记——03. 磁盘分区

    Everything is a file. 常见硬件对应于 Linux 下的文件(/dev目录下) 装置 装置在Linux内的档名 SCSI/SATA/U盘硬盘机 /dev/sd[a-p] U盘 /d ...

  6. 鸟哥的linux私房菜学习笔记 __ 命令与文件的搜寻

    连续输入两次[tab]按键就能够知道使用者有多少命令可以下达.那你知不知道这些命令的完整档名放在哪里?举例来说,ls 这个常用的命令放在哪里呢? 就透过 which 或 type 来找寻吧! 范例一: ...

  7. 【鸟哥的Linux私房菜】笔记

    操作系统核心的功能! 驱动程序与操作系统的关系 2. [计算机组成之组件] 3.CPU实际要处理的数据完全来自于主存储器,这是一个很重要的概念! 4.CPU是整个计算机系统最重要的部分,那么目前世界上 ...

  8. 《鸟哥的Linux私房菜》笔记——04. 简单命令行

    键入命令 [dmtsai@study ~]$ command [-options] parameter1 parameter2 ... 指令 選項 參數(1) 參數(2) 注意:有时也可以使用 + 放 ...

  9. 鸟哥的Linux私房菜学习笔记——文件权限与目录配置

    Linux的文件权限和目录配置 在linux中的每个用户必需属于一个组,不能独立于组外.在linux中每个文件有所有者.所在组.其它组的概念. (1)所有者 一般为文件的创建者,谁创建了该文件,就是天 ...

  10. 鸟哥的Linux私房菜学习笔记(1)

    2014/10/29 1.档案的权限管理分为三个部分: 拥有者.群组.其他 2.ls -al 命令可以看到档案的详细信息 3.档案的属性中由十个部分构成 第一个部分是档案类型 -代表档案.d代表文件夹 ...

随机推荐

  1. ansii、unicode、utf8 区别和关系

    本地化过程中涉及到源文件和目标文件的传输问题,这时候编码就显得很重要.中文的网页和操作系统中通常采用ANSI编码,这也是微软OS的一个字符标准.对于ANSI,不同的国家和地区制定了不同的标准,由此产生 ...

  2. httpclient模拟浏览器get\post

    一般的情况下我们都是使用IE或者Navigator浏览器来访问一个WEB服务器,用来浏览页面查看信息或者提交一些数据等等.所访问的这些页面有的仅 仅是一些普通的页面,有的需要用户登录后方可使用,或者需 ...

  3. C++ Tempatet之模板模型

    模板一共有三种类型: 1.第一种包含模型:包含模型是讲模板的定义和声明都放在头文件里(注:一般我们写的代码是将声明放在头文件里,实现放在cpp里,防止产生两份实现代码) 缺点:包含模型会增加代码的量. ...

  4. Core Data数据库迁移

    一. Lightweight Migration i. 适合场景 Simple addition of a new attribute Removal of an attribute A non-op ...

  5. KMP--路过

    HDU 1358:弄清楚了NEXT,就好解决,还有不要再循环中用strlen;会超 ----------------------我是凑字数的------------------还是不会KMP----- ...

  6. HTTP报头详解

    HTTP头字段包括4类:      general-header ; 通用报头      request-header ; 请求报头      response-header ; 响应报头      ...

  7. oracle OVER(PARTITION BY) 函数

    OVER(PARTITION BY)函数介绍 开窗函数               Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是:对于每个组返 ...

  8. BZOJ1191: [HNOI2006]超级英雄Hero

    这题标解是改一下匈牙利算法,显然,像我这种从不用匈牙利的人,会找个办法用网络流… 具体做法是这样,二分最后的答案ans,然后对前ans个问题建图跑网络流,看最大流能不能到ans. /********* ...

  9. WCF传输Dataset大数据量 -压缩

    由于WCF不能传输DataTable(不能序列化),所以更多项目中都会使用DataSet作为查询集合的首选返回类型,但是由于DataSet会生成很多的状态信息等,所以DataSet体积也会变大,有几种 ...

  10. hdu 4753 Fishhead’s Little Game 博弈论+记忆化搜索

    思路:状态最多有2^12,采用记忆化搜索!! 代码如下: #include<iostream> #include<stdio.h> #include<algorithm& ...