成都网站推广
 

中联无限-服务热线:028-86637122 工作时间:9:00-18:00 星期一-星期五

 
首页 | 关于我们 | 新闻动态 | 成都网站建设 | 成都网站推广 | 成都微信营销 | 网站制作案例 | 软件开发 | 常见问题 | 域名注册 | 虚拟主机
  网站知识
     推荐工具 / Tools
     网站运营/Operation
  
  客户案例
·巨丰达人减肥训练营
·成都写意经典家具有限公司
·成都卡姆士安防设备有限公司
·新千里装饰集团
·成都吕氏三才中医博爱堂
·泊菲特语言学校
·四川高地易景园林工程公司
·成都烽火建筑装饰设计有限公司
·优尼客酒店
·成都杜嘉机电有限公司
·菲颖1购
·成都安东尼体育文化传播有限公
·四川九章生物化工科技发展有限
·成都环球体育文化传播有限公司
·万友爱淘网上商城
·四川省斯博兰德建筑装饰设计有
·肥犇仔
·成都市猛追湾游泳场
  网站运营
·企业新站推广中存在的六大误区
·网站运营之八大要素
·怎么区别网站运营与网络运营
·怎样区分网站运营和网络运营
·SQL Server 200
·新网站运营后如何迅速增加网站
·减肥网站是怎样提高收入的
·个人网站赢利模式的拓展方向
·商业门户网站运营模式探讨
·成都地方门户网站运营模式
·网站策划人如何盈利
·网站运营模式观察与分析
  最新资讯
·成都网络推广公司介绍的六种推
·分析导致成都网络推广效果差的
·成都网站优化:企业网站关键词
·成都网站优化初期企业应该需要
·浅析成都网站优化中企业如何建
·分析企业在做成都网站优化过程
·短视频营销可以为成都网络推广
·小品牌怎么样才能既省钱又省力
·分析成都网络推广中企业需要注
·如何根据成都网络推广的营销周
·成都网站优化需要遵循哪些规则
·成都SEO网站优化过程中如何
 
   您的位置在:成都网站推广 > 网站知识 > 网站教程 /Tutorial > 正文
   网站教程 /Tutorial

PHP内存池中的存储层

[ 来源:中联无限科技有限公司   发布日期:2011/1/4 10:04:04 ]

实例说明PHP内存池中的存储层的工作原理!

PHP的内存管理器分为三层:存储层(storage)、堆(heap)层和 emalloc/efree 层。

存储层通过 malloc()、mmap() 等函数向系统真正的申请内存,并通过free()函数释放所申请的内存。

  存储层通常申请的内存块都比较大,这里申请的内存大并不是指storage层结构所需要的内存大,只是堆层通过调用存储层的分配方法时,其以段的格式申请的内存比较大,存储层的作用是将内存分配的方式对堆层透明化。

  首先看storage层的结构:

 

  1. /* Heaps with user defined storage */    
  2. typedef struct _zend_mm_storage zend_mm_storage;    
  3.      
  4. typedef struct _zend_mm_segment {    
  5.     size_t    size;    
  6.     struct _zend_mm_segment *next_segment;    
  7. } zend_mm_segment;    
  8.      
  9. typedef struct _zend_mm_mem_handlers {    
  10.     const char *name;    
  11.     zend_mm_storage* (*init)(void *params);    //初始化函数    
  12.     void (*dtor)(zend_mm_storage *storage);    //析构函数    
  13.     void (*compact)(zend_mm_storage *storage);    
  14.     zend_mm_segment* (*_alloc)(zend_mm_storage *storage, size_t size);    //内存分配函数    
  15.     zend_mm_segment* (*_realloc)(zend_mm_storage *storage, zend_mm_segment *ptr, size_t size);    //重新分配内存函数    
  16.     void (*_free)(zend_mm_storage *storage, zend_mm_segment *ptr);    //释放内存函数    
  17. } zend_mm_mem_handlers;    
  18.      
  19. struct _zend_mm_storage {    
  20.     const zend_mm_mem_handlers *handlers;    //处理函数集    
  21.     void *data;    
  22. };    

  内存的分配方式,调用的函数是_zend_mm_storage结构中的处理函数集,而内存是以段的形式表现的。

  4种内存方案

  PHP在存储层共有4种内存分配方案: malloc,win32,mmap_anon,mmap_zero。默认使用malloc分配内存,如果设置了ZEND_WIN32宏,则为windows版本,调用HeapAlloc分配内存,剩下两种内存方案为匿名内存映射,并且PHP的内存方案可以通过设置变量来修改。

  官方说明如下:

  The Zend MM can be tweaked using ZEND_MM_MEM_TYPE and ZEND_MM_SEG_SIZE environment variables. Default values are “malloc” and “256K”.Dependent on target system you can also use “mmap_anon”, “mmap_zero” and “win32″ storage managers.

  在代码中,对于这4种内存分配方案,分别对应实现了zend_mm_mem_handlers中的各个处理函数。配合代码的简单说明如下:

 

  1. /* 使用mmap内存映射函数分配内存 写入时拷贝的私有映射,并且匿名映射,映射区不与任何文件关联。*/    
  2. # define ZEND_MM_MEM_MMAP_ANON_DSC {"mmap_anon", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_anon_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free}    
  3.    
  4. /* 使用mmap内存映射函数分配内存 写入时拷贝的私有映射,并且映射到/dev/zero。*/    
  5. # define ZEND_MM_MEM_MMAP_ZERO_DSC {"mmap_zero", zend_mm_mem_mmap_zero_init, zend_mm_mem_mmap_zero_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_zero_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free}    
  6.    
  7. /* 使用HeapAlloc分配内存 windows版本 关于这点,注释中写的是VirtualAlloc() to allocate memory,实际在程序中使用的是HeapAlloc*/    
  8. # define ZEND_MM_MEM_WIN32_DSC {"win32", zend_mm_mem_win32_init, zend_mm_mem_win32_dtor, zend_mm_mem_win32_compact, zend_mm_mem_win32_alloc, zend_mm_mem_win32_realloc, zend_mm_mem_win32_free}    
  9.    
  10. /* 使用malloc分配内存 默认为此种分配 如果有加ZEND_WIN32宏,则使用win32的分配方案*/    
  11. # define ZEND_MM_MEM_MALLOC_DSC {"malloc", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_malloc_alloc, zend_mm_mem_malloc_realloc, zend_mm_mem_malloc_free}    
  12.    
  13. static const zend_mm_mem_handlers mem_handlers[] = {    
  14. #ifdef HAVE_MEM_WIN32    
  15.     ZEND_MM_MEM_WIN32_DSC,    
  16. #endif    
  17. #ifdef HAVE_MEM_MALLOC    
  18.     ZEND_MM_MEM_MALLOC_DSC,    
  19. #endif    
  20. #ifdef HAVE_MEM_MMAP_ANON    
  21.     ZEND_MM_MEM_MMAP_ANON_DSC,    
  22. #endif    
  23. #ifdef HAVE_MEM_MMAP_ZERO    
  24.     ZEND_MM_MEM_MMAP_ZERO_DSC,    
  25. #endif    
  26.     {NULL, NULL, NULL, NULL, NULL, NULL}    
  27. };    

  关于匿名内存映射的优点

  mmem_zero方案:

       (SVR 4 ) /dev/zero Memory Mapping 

  1. 可以将伪设备 “/dev/zero” 作为参数传递给mmap而创建一个映射区。/dev/zero的特殊在于,对于该设备文件所有的读操作都返回值为0的指定长度的字节流 ,任何写入的内容都被丢弃。我们的兴趣在于用它来创建映射区,用/dev/zero创建的映射区,其内容被初始为0。

  2. 使用/dev/zero的优点在于,mmap创建映射区时,不需要一个时间存在的文件,伪文件 /dev/zero 就足够了。缺点是只能用在相关进程间。相对于相关进程间的通信,使用线程间通信效率要更高一些。不管使用那种技术,对共享数据的访问都需要进行同步。

  mmem_anon方案:

  (4.4 BSD) Anonymous Memory Mapping

  1. 匿名内存映射与使用/dev/zero类型,都不需要真实的文件。要使用匿名映射之需要向mmap传入MAP_ANON标志,并且fd参数置为-1。

  2. 所谓匿名,指的是映射区并没有通过fd与文件路径名相关联。匿名内存映射用在有血缘关系的进程间。

  win32方案中堆内存分配的声明

  函数HeapAlloc声明如下:

 

  1. WINBASEAPI    
  2. __out_opt    
  3. HANDLE    
  4. WINAPI    
  5. HeapCreate(    
  6.  __in DWORD flOptions,    
  7.  __in SIZE_T dwInitialSize,    
  8.  __in SIZE_T dwMaximumSize    
  9.  );    
  10.      
  11. WINBASEAPI    
  12. BOOL    
  13. WINAPI    
  14. HeapDestroy(    
  15.  __in HANDLE hHeap    
  16.  );    
  17.      
  18. WINBASEAPI    
  19. __bcount(dwBytes)    
  20. LPVOID    
  21. WINAPI    
  22. HeapAlloc(    
  23.  __in HANDLE hHeap,    
  24.  __in DWORD dwFlags,    
  25.  __in SIZE_T dwBytes    
  26.  );    
  27.      
  28.      
  29. WINBASEAPI    
  30. BOOL    
  31. WINAPI    
  32. HeapFree(    
  33.  __inout HANDLE hHeap,    
  34.  __in DWORD dwFlags,    
  35.  __deref LPVOID lpMem    
  36.  );    
  37.      
  38. WINBASEAPI    
  39. SIZE_T    
  40. WINAPI    
  41. HeapSize(    
  42.  __in HANDLE hHeap,    
  43.  __in DWORD dwFlags,    
  44.  __in LPCVOID lpMem    
  45.  );   

◆hHeap是进程堆内存开始位置。

◆dwFlags是分配堆内存的标志。

◆dwBytes是分配堆内存的大小。

  初始化

  在zend_mm_startup启动时,程序会根据配置设置内存分配方案和段分配大小,如下所示代码:

 

  1. ZEND_API zend_mm_heap *zend_mm_startup(void)    
  2. {    
  3.     int i;    
  4.     size_t seg_size;    
  5.     char *mem_type = getenv("ZEND_MM_MEM_TYPE");    
  6.     char *tmp;    
  7.     const zend_mm_mem_handlers *handlers;    
  8.     zend_mm_heap *heap;    
  9.      
  10.     if (mem_type == NULL) {    
  11.      i = 0;    
  12.     } else {    
  13.      for (i = 0; mem_handlers[i].name; i++) {    
  14.       if (strcmp(mem_handlers[i].name, mem_type) == 0) {    
  15.        break;    
  16.       }    
  17.      }    
  18.      if (!mem_handlers[i].name) {    
  19.       fprintf(stderr, "Wrong or unsupported zend_mm storage type '%s'\n", mem_type);    
  20.       fprintf(stderr, "  supported types:\n");    
  21.       for (i = 0; mem_handlers[i].name; i++) {    
  22.        fprintf(stderr, " '%s'\n", mem_handlers[i].name);    
  23.       }    
  24.       exit(255);    
  25.      }    
  26.     }    
  27.     handlers = &mem_handlers[i];    
  28.      
  29.     tmp = getenv("ZEND_MM_SEG_SIZE");    
  30.     if (tmp) {    
  31.      seg_size = zend_atoi(tmp, 0);    
  32.      if (zend_mm_low_bit(seg_size) != zend_mm_high_bit(seg_size)) {    
  33.       fprintf(stderr, "ZEND_MM_SEG_SIZE must be a power of two\n");    
  34.       exit(255);    
  35.      } else if (seg_size < ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE) {    
  36.       fprintf(stderr, "ZEND_MM_SEG_SIZE is too small\n");    
  37.       exit(255);    
  38.      }    
  39.     } else {    
  40.      seg_size = ZEND_MM_SEG_SIZE;    
  41.     }    
  42.      
  43.     //....代码省略    
  44. }    

  第1121~1138行遍历整个mem_handlers数组,确认内存分配方案,如果没有设置ZEND_MM_MEM_TYPE变量,默认使用malloc方案,如果是windows(即ZEND_WIN32),则默认使用win32方案,如果设置了ZEND_MM_MEM_TYPE变量,则采用设置的方案。

  第1140~1152行确认段分配大小,如果设置了ZEND_MM_SEG_SIZE变量,则使用设置的大小,此处会判断所设置的大小是否满足2的倍数,并且大于或等于ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE;如果没有设置没使用默认的ZEND_MM_SEG_SIZE。


上一篇:有关网站关键词的选取与推广方法
下一篇:CSS网页技术基本语法
   相关网站教程 /Tutorial
·SEO之如何更好的布局?2011-08-11
·Ajax2011-05-26
·JSP的定义2011-05-26
·PHP是什么2011-05-26
·CSS教程:CSS背景全攻略2011-03-26
·javascript cookies 存2011-03-25
·网站外部链接的注意事项2011-03-24
·PHP防御木马攻击的技巧2011-03-11
·Apache服务器的配置与管理2011-03-11
·SQL Server数据库查询优化的常用2011-03-09
·SQL Server触发器2011-03-09
·ASP.NET JMAIL 发送邮件方法2011-03-09
首页 | 公司简介 |联系方式 |付款方式 |人才招聘 | 域名空间 | 网页设计案例 | 网站知识 | 解决方案 | 建站指南 | 网站地图
地址:成都市青羊区西大街1号   邮编:610041   E- Mail:619027769@qq.com   代理合作: 028-86637122
网站建设/推广咨询:028-86637122  86618860  传真:028-86637322   
成都中联无限科技有限公司 2004-2014    蜀ICP备05017733号