Php运行时的内存分布

还是首先先贴结论,Php运行时的内存分布是这样的:

Php运行时的内存分布

其中 .data 是经过初始化的静态变量的数据 (实际上经过初始化的全局变量的值,还有常量也在 .data 里面),.bbs 是静态变量但是没有初始化,其实 .bbs 就是这个内存划分上有这么一个区域,实际上因为它没初始化,所以实际上也没有占用空间。shm 指的是共享内存内存空间(shm 我暂时不太理解)。

好了,基本上就是上面这样。下面我再详细说明一下 栈 堆 以及数据在内存中存储的一些底层原理。

CPU 寄存器 内存

CPU

Cpu…(这里不想复杂的说它由那些部分组成了) 简单来说它是负责处理指令的一个设备,比较传统的评估Cpu性能的方式,就是计算这个cpu处理一个指令需要多少个时钟周期,这里时钟周期指的是什么呢,简单来说就是 Cpu 的频率。这个时钟周期什么概念呢? 举个例子,比如程序员A从接需求到完成任务是按星期算的,一星期做一个任务就是他的时钟周期。Cpu 的主要工作就是取数据然后执行,4GHz 指的是 Cpu 每秒可以进行4G次取-执行操作, 频率高不一定性能就好,频率高只是一方面,比如 CPU 小A 和 小B 他俩每秒都能接10个活,但是小A瞬间就出结果了,小B还得等一会儿,这样。

寄存器

寄存器是CPU的一部分,Cpu 从内存中拿到数据之后会放在寄存器里,比如算一个加法,就是把数字拿出来然后给寄存器里的数字加一。寄存器有很多种,比如内存地址寄存器,还有记录当前执行位置的指令计数器等等。

内存

内存是负责存储数据的一个设备,它存数据是先按位存,比如这一位是一个 1 内一位是个 0 ,然后再按行存, 你可以把它想象成一行又一行的 0 和 1 。内存是怎么寻址的呢? 就是通过内存地址寄存器和一个地址译码器。比如这个内存有32根线连在主板上,那么从第一根到到最后一根就是 0-32。 然后每次从第一根到最后一根这些线组成一行, 比如我要查第5行的第 0-16 位数据,按照这种方式是能找的到的。
按照上面的方式可以解决数据的存储问题,但是实际使用中可能出现以下几种情况

  1. 当新程序进入系统时,碎片化使操作系统越来越难以找到足够大的空间装载新程序
  2. 操作系统必须避免一个程序修改了另一个程序的内存,这意味着一开始分配内存的时候需要特别小心的分配内存
  3. 内存总是会不够用。

虚拟内存

为了解决上面的问题,操作系统提供了一种基于分页技术的虚拟内存。简单的来说就是先把内存分块,每一块称为一帧,所有的帧都是大小相等的。然后这些块都有一个起始的地址,然后块内部的地址就是起始地址的相对地址,这样操作系统只要管理块的地址,就不用关心每一位的地址了。然后程序这边也分成块,每一块的大小和内存里的帧一样大,程序里的块称为页。 然后操作系统会为每个程序产生一个页表,页表里存了每一页的页号和帧号。这样程序编译的时候其实不用考虑实际的内存地址,只要考虑自己的页和页号就好了。实际上,编译好的程序里面的内存地址,其实就是虚拟的内存地址,实际的物理内存地址是操作系统底层进行分配的,所以程序员写代码的时候就不用考虑内存冲突的问题了。

这里指的栈其实是程序运行时的用户栈,而不是别的什么栈。上面提到Cpu在处理指令的时候会先把数据拿到寄存器,然后再进行执行。但是每个cpu只有一套通用寄存器,比如 Cpu 先执行方法 a, 然后把方法 a 的数据拿到寄存器了,然后 a 调用了 b 方法,这时候要执行 b 方法,这寄存器里面已经有 a 的方法了怎么办,就是先找个地方把 a 的东西存起来,然后执行 b 方法。 这个临时存东西的地方就是栈。
下面我详细描述一下这个过程

  1. a 将入口参数放在 b 能访问到的地方
  2. a 将返回地址存到特定的地方,然后将控制权转给 b
  3. b 保存 a 的现场(a在寄存器里的数据),并为自己的非静态局部变量分配空间(在栈中)
  4. 执行 b
  5. b 执行完毕后恢复 a 的现场(将 a 刚才的数据写回寄存器),释放自己在栈中占用的内存
  6. b 取出 a 的返回地址,将控制权交给 a

相信大家看到这已经了解了什么是栈,以及它是干嘛用的了。它其实就是内存上的一块空间,用来存放函数运行时的局部变量和数据。从程序的角度看栈占用的空间大小不是固定的,它在运行时有一个不间断的入栈和出栈。从函数的角度看,每一个函数都有自己的栈,存放着调用自己的函数的现场,自己的参数,以及自己的返回地址。

上面提到了栈,堆其实和栈也一样也是在运行时存放函数的变量和数据,只不过堆用来存放的是大小不确定的数据。 还是举个例子比如说 a 调用 b 了,b 写入的时候要跟在 a 的后面, 栈在内存上是一块连续的区域有上下文的。但是这个时候 a 的局部变量里有一个变量的大小不确定(编译时不确定)。比如在我电脑我名字两个字,他占两个字的空间。在四个字的人的电脑上占四个字的空间。 cpu 执行代码的时候是按顺序执行的,执行到这里要跳转了,一看 a 的空间不确定,怎么办呢,而且 cpu 有时候也特别傻, 执行到这里要跳转了, 它就是要跳转,不会像人类一样随机应变。 所以这种情况下, 对于大小不确定的变量,事先就把它放到另外一个地方,栈的空间就是确定的空间,不会出现意外了。堆负责存的就是大小不确定的变量。
php 对堆和栈没啥概念,但是在 php 的底层实现 c 哪里是有区别的 。c 语言中堆基本上指的就是手动分配的内存。 堆和栈都是在内存里面, 存取速度应该没有影响。 对于垃圾回收可能会有影响,因为 c 里面手动分配的内存(堆)是一定要手动释放的,否则会导致内存泄漏。php 有一套比较复杂的垃圾回收机制,大概是引用计数加一个垃圾回收算法,就是把可能没有被引用的变量加到一个缓存池里,然后每隔一段时间或者缓存池满了,就通过一个算法判断是不是真的没有被引用了,如果是的话就释放内存空间。老早以前听说 jvm 使用定时器进行垃圾回收,回收垃圾的时候会影响性能,当时还嘲笑了一波。没想到 php 也是这样,还好 java 程序应该不知道,不会反过来嘲笑我。

一号要去新公司上班了,源码学习可能会中断一段时间了,也不知道会不会顺利,祝好运吧。

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!