
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
Linux编程开发语言随着互联网的不断发展而被越来越多的程序员掌握,今天我们就通过案例分析来简单了解一下,Linux编程内存分配方法都有哪些。
在Linux中,内存的分配通常由C标准库提供的内存分配函数malloc()实现
当malloc()函数需要分配内存时,它会调用这两个系统调用——即brk()和mmap()
brk()
对于小块内存(小于128K大于4K),使用brk()来分配,通过移动堆顶的位置来分配内存
这些内存释放后并不会立刻归还系统,而是被缓存起来,这样就可以重复使用
优缺点:
减少缺页异常的发生,提高内存访问效率
由于不会立刻归还释放的内存给系统,所以在内存工作繁忙时,频繁的内存分配和释放会造成内存碎片
mmap()
对于大块内存(大于128K),则直接使用内存映射mmap()来分配,也就是在文件映射段找一块空闲内存分配出去,释放时直接归还系统
优缺点:
在释放时直接归还系统,所以每次mmap都会发生缺页异常
在内存工作繁忙时,频繁的内存分配会导致大量的缺页异常,使内核的管理负担增大。这也是malloc只对大块内存使用mmap的原因
需要注意的是,一开始调用内存分配函数的时候,其实是没有真正分配到物理内存
只有在进程次访问时才分配,即通过缺页异常进入内核中,再由内核来分配内存
Linux伙伴系统(buddy)
在Linux中,光知道如何分配内存还不行,还得知道该怎么分配
伙伴管理器是Linux系统中一种常见的内存分配算法,它可以让系统在分配物理内存时,快速地找到相应大小的可用内存块
前面说到,MMU是一种硬件设备,负责虚拟内存和物理内存的映射关系。当内核需要访问某个虚拟内存时,MMU将该虚拟地址转换为对应的物理内存地址,并通过伙伴系统的分配算法来定位相应的内存块
当内存释放时,伙伴系统将其标记为空闲,用于重新分配给其他进程。因此,伙伴系统和MMU相互协作,实现Linux操作系统的内存管理功能
上面说到,对于4K至128K的内存用brk()来分配,对于大于128k的内存使用内存映射mmap()来分配。那如果要分配的内存小于4K呢?
实际系统运行的时候,有着许多内存小于4K的对象,如果为他们分配单独的页,那就太浪费内存了
所以Linux通过下面两种方式来分配小于4K的内存:
1、伙伴系统
当需要分配小于4K的内存时,内核会为之保留一个完整的物理页,并尽量将物理页分割成大小相同的小块。当有多个小块被请求时,内核会合并这些小块,终分配
2、slab分配器
slab分配器是Linux内核中的一个重要组成(你可以将slab看成构建在伙伴系统上的一个缓存)它将一小块内存分配称为缓存(cache)
当需要分配小于4K的内存时,Slab分配器会创建一个小的缓存来保存请求内存的块。每个缓存都有一个物理页的大小
如果已经分配完了所有内存块,Slab分配器会重新分配一个完整的物理页作为缓存,以供后续请求使用
为了防止内存碎片化,slab分配器会保留已经使用完的slab块并重复使用其中未被使用的空间,而不是将其释放回系统
内存回收
如果内存只分配而不释放,就会造成内存泄漏,甚至会耗尽系统内存
所以,在应用程序用完内存后,还需要调用free()或unmap(),来释放这些不用的内存
那么系统是如何回收内存的呢?
1、使用LRU(LeastRecentlyUsed)算法,回收近使用少的内存页面
2、回收不常访问的内存,把不常用的内存通过交换分区(swap)直接写到磁盘中
Swap其实就是把一块磁盘空间当成内存来用
它可以把进程暂时不用的数据存储到磁盘中(这个过程称为换出),当进程访问这些内存时,再从磁盘读取这些数据到内存中(这个过程称为换入)
通常只在内存不足时,才会发生Swap交换。并且由于磁盘读写的速度远比内存慢,Swap会导致严重的内存性能问题
3、杀死进程,内存紧张时系统还会通过OOM(OutofMemory),直接杀掉占用大量内存的进程
【免责声明】本文系本网编辑部分转载,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请在30日内与管理员联系,我们会予以更改或删除相关文章,以保证您的权益!请读者仅作参考。更多内容请加抖音太原达内IT培训学习了解。