### C语言的内存分配和释放
- c是通过malloc函数申请一块连续的指定大小的内存块区域。其作用是在内存的动态存储区中分配一个长度为size的连续空间。成功则返回一个指向内存首地址的指针,内存分配失败则返回空指针NULL
- 内存使用完后调用free函数将内存块释放。在内存释放的时候,不需要传入内存的大小,因为malloc实现的时候,会比传入的size多分配32位即4字节,第3位至31位用来存储块的大小,因此释放内存的时候,通过首地址,往前移动4字节,就可以取到该快的大小值。
- **如何处理释放后的空闲的内存块呢**?
内存分配和释放会导致内存被分割成若干个大小不一样的内存块,其中有些处于已分配状态,有些处于空闲状态,这两个状态就是通过多分配的4字节中的一个比特位来记录的,标志位1表示已分配,0表示空闲。空闲块可能会被组织成一个链表,遍历空闲块链表就可能查找到合适的内存。

- **内存池**
由于频繁malloc分配内存块会导致效率低下(如根据算法找出合适的内存块、调用free等释放内存并且可能会合并空闲块)而且会产生很多内存碎片,也很容易造成内存泄漏。还有可能因申请不到合适的内存导致系统运行不稳定。
因此,内存池就是用来解决上述问题的,由系统提前分配好各种大小的内存,当程序需要申请内存的时候,先去内存池中查找,这样就不用频繁申请和释放内存了
## php内存分配和释放
### 内存管理器
- 使用Zend Memory Manager(Zend内存管理器)来管理内存,PHP脚本运行所需要的内存空间不是直接从系统中申请,而是调用Zend内存管理器提供的一系列接口函数(如zend\_mm\_alloc\_small)申请:如果Zend内存管理器中的可用内存够用,直接分配给PHP查询;否则,Zend内存管理器再从系统中申请。这样能有效减少系统调用的次数,并优化内存空间的使用效率。
### 内存分配思想
- 通过mmap函数向系统申请大块内存(n * chunk大小的内存),再按固定的几种规则分割成较小的内存块,由内存池统一管理。当调用方申请内存时,从池子中匹配已经预分配的合适大小的内存块返回。
### 内存分类的规则
PHP7维护了3种大小的内存规格(chunk, page, slot)
- 每个chunk大小为2MB
- 每个page大小为4KB
- 一个chunk可以分割成512个page,一个page又可以分割成n个不同大小规模的slot
- 对于Zend内存管理器而言,只有chunk是通过malloc从系统中申请的内存
PHP7将Zend内存管理器申请内存按大小分成了3类:
1. **small内存**:size<=3KB,一共有30种规格大小,每当有分配请求时,在对应的空闲链表取合适的,若不存在合适的,则从chunk上的page分割出合适的。(具体分割看下面的“small内存分配”)
2. **large内存**:3KB<size<=(2MB-4KB),在chunk上查找满足条件的若干个连续page,最终返回的大小为4K的整数倍。
3. **huge内存**:size>2M-4K,直接调用mmap分配2M的整数倍大小的内存。
- linux 基础
- ln 链接
- linux 环境变量
- linux 进程查看
- nginx
- redis
- redis 安装
- php 底层原理
- php源码编译安装
- phpize文件
- php命令行
- php7 新特性
- php7 变量
- php7 生命周期
- php sapi运行模式
- php 内存管理
- php 运行机制和Zend虚拟机
- php垃圾回收
- php 基础
- php.ini
- php函数
- 面向对象
- php 文件上传
- ob缓冲和页面静态化
- php中的session
- php cURL扩展
- composer 应用
- php 错误和异常
- thinkphp
- tp6容器和依赖注入
- tp6 的服务
- tp6事件
- tp6 多应用
- tp6路由
- tp6 cache
- tp6 request
- tp6 中间件
- tp6 response
- tp6 Db
- 备忘录
- 数据库表