美文网首页
linux-04-内存管理函数

linux-04-内存管理函数

作者: vera姐姐 | 来源:发表于2016-05-10 12:05 被阅读138次

    今天:-malloc() free() sbrk() brk() mmap() munmap()

    文件读写函数(UC版)

    malloc() 和 free()

    malloc()分配的是堆区的内存 一次申请小块内存时,系统会映射33个内存页,如果申请大块内存(31个内存页以上),系统会映射比申请稍多一点的内存页数。

    malloc申请内存时,除了数据占用的空间外,还需要额外占用一些空间,用于存储附加数据。malloc申请内存时,会包括三部分:数据本身的空间,附加数据的空间,空的空间(预留空间)。附加数据存于 底层维护的双向链表中。预留空间的大小不确定,可大可小。

    int* pi = malloc(4);

    free(pi);//free()释放到哪里结束呢? 附加数据中有。

    理论上因为malloc()会映射多个内存页,导致未分配的内存只要在33页之内都能使用;但是为了便于内存的管理(反复使用和控制),内存还是要 先分配再使用。

    free()一定会释放被占用的虚拟内存地址,但是不一定会解除内存映射,对于malloc()来说,free()不会释放最后的33个内存页映射。最后33个内存页的映射在进程结束时才会释放。free()在大多数情况下会清空内存,但是不保证清()

    free对于申请大块内存时会 全部解除映射。

    经验:malloc()虽然地址不连续,但是不影响内存的使用;malloc()申请的内存在使用时不要过界,否则会影响下一次的内存分配和回收。

    sbrk()和brk()

    sbrk()和brk()是Unix的系统函数,机制和malloc是完全不同的。借助系统维护的一个位置进行内存的分配和回收。

    void* sbrk(int increment) 功能就是分配//回收内存,大多数情况下用于分配内存。

    参数increment是分配/回收的增量,为正数分配,为负数时,回收,为0时候取当前值。

    返回值返回移动之前的位置,如果出错返回(void*) -1.

    sbrk()在分配内存时非常方便,但回收内存时需要计算字节数,因此比较麻烦,不便于管理。brk()则相反。

    一般情况下都是使用sbrk()分配内存,使用brk()释放内存(虽然这两个函数都可以分配和回收)。

    sbrk()和brk()都是以一个内存页作为映射的基本单位的,一旦释放就会同时解除内存映射。

    int brk(void* position) 功能就是分配/回收内存,一般用于回收内存

    参数position就是新位置,无论原来的位置在哪里。返回:成功返回0,失败返回 -1。

    brk() 和sbrk() 不会清除回收内存的数据,数据会在下次使用时被覆盖。

    memset()可以设置内存的内容,一般用于清内存;

    memcpy()可以复制内存的内容,一般用内存复制。

    mmap() 和munmap()

    用户层能使用的功能最强大的函数,可以设置一些内存相关的数据。mmap()实现内存映射,包括:映射物理内存和硬盘文件

    各种权限和多个选项用位或 | 连接。

    RWX

    R-- 100

    -W- 010

    --X 001

    读+写

    100 | 010

    void* mmap(void* addr,size_t length, int prot, int flats, int fd, off_t offset)

    功能是内存映射,比sbrk()功能强大的多,失败返回-1

    参数:addr指定映射的首地址,为0就是交给内核选择。

    size 就是映射内存的大小

    prot 就是内存的权限 一般是PROT——READ|PROT——WRITE

    flats 就是映射的标识 主要包括:

    MAP_SHARD MAP_PRIVATE 2选1,

    MAP_SHARED 代表这块内存其他进程可以共享,但只对映射文件有效

    MAP_PRIVATE就是其他进程不能共享,只能本进程使用。

    MAP——ANONYMOUS代表映射 物理内存,不写就映射硬盘文件(默认映射)。

    fd 是文件描述符,映射文件时有效,映射物理内存为0.

    offset 是文件偏移量,选择映射文件的位置,映射物理内存 为0;

    返回:成功返回映射的首地址,失败返回MAP——FAILED

    用户空间的程序不能进入内核空间,但很多功能需要内核实现,因此内核空间 提供了一系列的函数, 允许用户空间调用,从而进入内核空间。这一系列的函数通称为 系统调用(system call)。比如:标C的malloc() 不能进入Unix内核,但内存分配必须依赖内核,内核提供了系统调用sbrk()和mmap(),帮助malloc()进入内核完成内存的分配。

    系统调用的使用方式和标C函数没有任何区别,因此无需过多关注。

    eg:

    int* pi =mmap(NULL,//首地址内核选择

    6              4,//分配4字节,映射还是按一页算

    7              PROT_READ | PROT_WRITE,//权限

    8              MAP_PRIVATE | MAP_ANONYMOUS,//映射物理内存用    PRIVATE,ANNONYMOU    S代表映射物理内存

    9              0,0);//文件描述符映射物理内存给()

    10  if(pi == MAP_FAILED)

    11  {

    12    perror("MMAP");

    13    return -1;

    14  }

    15  *pi = 100;

    16 printf("%d\n",*pi);

    17 munmap(pi,4);

    相关文章

      网友评论

          本文标题:linux-04-内存管理函数

          本文链接:https://www.haomeiwen.com/subject/nehyrttx.html