首页 | 资讯动态 | linux基础 | 系统管理 | 网络管理 | 编程开发 | linux数据库 | linux相关 | linux认证 | 下载中心 | 专题
oklinux
 系统管理:中文环境 系统管理 桌面应用 内核技术 Linux基础:安装配置 常用命令 经验技巧 软件应用 Linux数据库:Mysql POSTGRE
 网络管理:网络安全 网络应用 Linux服务器 编程开发:PHP CC++ Python Perl SHELL 嵌入式开发 | PHP基础 PHP技巧 PHP应用 PHP文摘
 首页 linux资讯动态 Linux专题 | 其他Unix Linux解决方案 硬件相关 Linux认证 企业应用 Apache | 相关下载:软路由 参考手册 开发工具
 → 当前位置:首页>编程开发>php>php应用>正文

通过案例深入探讨PHP中的内存管理问题

OKLinux www.oklinux.cn 2006-10-29 来源:oklinux收集整理 会员收藏 游客收藏

内存管理对于长期运行的程序,例如服务器守护程序,是相当重要的影响;因此,理解PHP是如何分配与释放内存的对于创建这类程序极为重要。本文将重点探讨PHP的内存管理问题。

  一、 内存

  在PHP中,填充一个字符串变量相当简单,这只需要一个语句"<?php $str = 'hello world '; ?>"即可,并且该字符串能够被自由地修改、拷贝和移动。而在C语言中,尽管你能够编写例如"char *str = "hello world ";"这样的一个简单的静态字符串;但是,却不能修改该字符串,因为它生存于程序空间内。为了创建一个可操纵的字符串,你必须分配一个内存块,并且通过一个函数(例如strdup())来复制其内容。

{
 char *str;
 str = strdup("hello world");
 if (!str) {
  fprintf(stderr, "Unable to allocate memory!");
 }
}

  由于后面我们将分析的各种原因,传统型内存管理函数(例如malloc(),free(),strdup(),realloc(),calloc(),等等)几乎都不能直接为PHP源代码所使用。

  二、 释放内存

  在几乎所有的平台上,内存管理都是通过一种请求和释放模式实现的。首先,一个应用程序请求它下面的层(通常指"操作系统"):"我想使用一些内存空间"。如果存在可用的空间,操作系统就会把它提供给该程序并且打上一个标记以便不会再把这部分内存分配给其它程序。
当应用程序使用完这部分内存,它应该被返回到OS;这样以来,它就能够被继续分配给其它程序。如果该程序不返回这部分内存,那么OS无法知道是否这块内存不再使用并进而再分配给另一个进程。如果一个内存块没有释放,并且所有者应用程序丢失了它,那么,我们就说此应用程序"存在漏洞",因为这部分内存无法再为其它程序可用。

  在一个典型的客户端应用程序中,较小的不太经常的内存泄漏有时能够为OS所"容忍",因为在这个进程稍后结束时该泄漏内存会被隐式返回到OS。这并没有什么,因为OS知道它把该内存分配给了哪个程序,并且它能够确信当该程序终止时不再需要该内存。

  而对于长时间运行的服务器守护程序,包括象


    除了提供隐式内存清除功能之外,ZendMM还能够根据php.ini中memory_limit的设置控制每一种内存请求的用法。如果一个脚本试图请求比系统中可用内存更多的内存,或大于它每次应该请求的最大量,那么,ZendMM将自动地发出一个E_ERROR消息并且启动相应的"跳出"进程。这种方法的一个额外优点在于,大多数内存分配调用的返回值并不需要检查,因为如果失败的话将会导致立即跳转到引擎的退出部分。

  把PHP内部代码和OS的实际的内存管理层"钩"在一起的原理并不复杂:所有内部分配的内存都要使用一组特定的可选函数实现。例如,PHP代码不是使用malloc(16)来分配一个16字节内存块而是使用了emalloc(16)。除了实现实际的内存分配任务外,ZendMM还会使用相应的绑定请求类型来标志该内存块;这样以来,当一个请求"跳出"时,ZendMM可以隐式地释放它。

  经常情况下,内存一般都需要被分配比单个请求持续时间更长的一段时间。这种类型的分配(因其在一次请求结束之后仍然存在而被称为"永久性分配"),可以使用传统型内存分配器来实现,因为这些分配并不会添加ZendMM使用的那些额外的相应于每种请求的信息。然而有时,直到运行时刻才会确定是否一个特定的分配需要永久性分配,因此ZendMM导出了一组帮助宏,其行为类似于其它的内存分配函数,但是使用最后一个额外参数来指示是否为永久性分配。

  如果你确实想实现一个永久性分配,那么这个参数应该被设置为1;在这种情况下,请求是通过传统型malloc()分配器家族进行传递的。然而,如果运行时刻逻辑认为这个块不需要永久性分配;那么,这个参数可以被设置为零,并且调用将会被调整到针对每种请求的内存分配器函数。

  例如,pemalloc(buffer_len,1)将映射到malloc(buffer_len),而pemalloc(buffer_len,0)将被使用下列语句映射到emalloc(buffer_len):

#define in Zend/zend_alloc.h:
#define pemalloc(size, persistent) ((persistent)?malloc(size): emalloc(size))

  所有这些在ZendMM中提供的分配器函数都能够从下表中找到其更传统的对应实现。

  表格(下)展示了ZendMM支持下的每一个分配器函数以及它们的e/pe对应实现:

  
你可能会注意到,即使是pefree()函数也要求使用永久性标志。这是因为在调用pefree()时,它实际上并不知道是否ptr是一种永久性分配。针对一个非永久性分配调用free()能够导致双倍的空间释放,而针对一种永久性分配调用efree()有可能会导致一个段错误,因为内存管理器会试图查找并不存在的管理信息。因此,你的代码需要记住它分配的数据结构是否是永久性的。

上一篇:Linux编程之提升PHP执行速度全攻略分析   下一篇:用PHP在Linux上读取输入并进行文件操作
收藏于收藏夹】 【评论】 【推荐】 【投稿】 【打印】 【关闭

相关文章
·Linux编程之提升PHP执行速度全攻略分析
·Linux下的编程PHP高级技巧全放送(三)
·如何用Butterfly XML IDE实现XML开发
·Linux下的编程PHP高级技巧全放送(二)
·Linux下的编程PHP高级技巧全放送(一)
·Linux编程:将PHP作为Shell脚本使用
·为什么PHP令人不爽(对于大型系统)
·如何利用PHP和CSS改变网页文字大小
·用php或js获取图片大小,高宽尺寸
·PHP实现简单线性回归之数据研究工具
发表评论
密码: 匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。)
站内搜索
阅读排行榜
·Windows服务器安装多套PHP
·PHP应用分页显示制作详细
·PHP也可以当成Shell Scrip
·如何使用动态共享对象的模
·用PHP编程语言开发动态WAP
·教您如何应用PHP开发出安
·PHP应用程序的性能优化及
·分析PHP比ASP优秀的七个理
·一步一步教你PHPMyAdmin安
·实例分析:实现一个PHP WA
最新文章
·在Redhat linux 9下让PHP
·Linux编程之提升PHP执行速
·Linux下的编程PHP高级技巧
·如何用Butterfly XML IDE
·Linux下的编程PHP高级技巧
·Linux下的编程PHP高级技巧
·Linux编程:将PHP作为Shel
·为什么PHP令人不爽(对于
·如何利用PHP和CSS改变网页
·用php或js获取图片大小,高
·PHP实现简单线性回归之数
·使用PHP的Socket写的POP3
·PHP编制搜索引擎的一些
·用PHP和AJAX创建RSS聚合器
·PHP4中实现动态代理

设为首页 - 加入收藏 - 版权声明 - 广告服务 - 关于我们 - 联系我们 - 友情连接
Copyright © 2007 All rights reserved OKLinux.Cn 版权所有
合作联系 QQ:18743986 Email:arlan8005#163.com