`
baiguomeng
  • 浏览: 958863 次
文章分类
社区版块
存档分类
最新评论

Apache数组分析

 
阅读更多
3.1数组
3.1.1数组概述
数组是Apache中最经常也是最普通的数据结构,尽管C语言中已经提供了一定的数组功能,但是C语言数组运用到Apache中还存在下面的一些问题:
(1)、C语言中的数组在定义的时候就必须确定维数目,一旦确定,其长度就不可更改。但是Apache中很多情况并不知道数组中能够保存的最大数目,如果预定义的太大,可能会浪费过多的空间;定义的太小又可能不能满足系统要求;因此Apache中需要一种动态的具有弹性伸缩能力的数组,这样实际需要多少元素就分配多少元素;
(2)、C语言中提供了另外一种数组动态伸缩的方案,即就是使用malloc分配空间,将空间看作数组进行处理。不过对于malloc分配的空间只能保存一种类型的数据。如果需要保存其余类型,则需要重新分配。
Apache中的数组实现方案类似于STL或者Java中的Vector,其长度可以保持动态变化,而且其中可以存放不同类型的数据,包括基本数据类型到复合数据类型。
3.1.2数组结构
Apache中相关的数组结构都定义在文件apr_table.h和apr_table.c中了。apr_array_header_t结构是Apache的核心结构,其定义如下:
struct apr_array_header_t {
apr_pool_t *pool;
int elt_size;
int nelts;
int nalloc;
char *elts;
};
数组的结构示意图片可以用下图表示:
图2.1 Apache数组结构图
apr_array_header_t结构中的elts指针指向了实际的用malloc分配的空间,每个空间的大小为elt_size。由于数组元素的个数是可以动态变化的,因此结构中使用nalloc记录当前已经分配的数组中的元素个数。另外由于Apache中的数组元素并不是所有的都被用到,因此还需要nelts记录当前已经使用的元素个数,自然剩余的可以利用的数组元素个数为nalloc-nelts。分配数组所需要的所有空间都从内存池pool中获取。
3.1.3创建数组
数组的创建通过调用apr_array_make实现,不过其内部主要工作由make_array_core实现:
static void make_array_core(apr_array_header_t *res, apr_pool_t *p,int nelts, int elt_size, int clear)
{
if (nelts < 1) {
nelts = 1;
}
if (clear) {
res->elts = apr_pcalloc(p, nelts * elt_size);
}
else {
res->elts = apr_palloc(p, nelts * elt_size);
}
res->pool = p;
res->elt_size = elt_size;
res->nelts = 0; /* No active elements yet... */
res->nalloc = nelts; /* ...but this many allocated */
}
APR_DECLARE(apr_array_header_t *) apr_array_make(apr_pool_t *p,int nelts, int elt_size)
{
apr_array_header_t *res;
res = (apr_array_header_t *) apr_palloc(p, sizeof(apr_array_header_t));
make_array_core(res, p, nelts, elt_size, 1);
return res;
}
apr_array_make函数负责主要用于分配apr_array_head_t头结构,而make_array_core则主要负责创建和初始化res元素数组。Res数组的大小中每一个元素的大小为elt_size,总元素个数为nelts,因此分配的总空间为nelts*elt_size,空间分配后继续初始化apr_array_header_t结构中的成员。如果clear为1,则调用apr_pcalloc进行分配,否则调用apr_palloc,两者唯一的区别就是apr_pcalloc会对分配的空间进行初始化清零;而apr_palloc则不会初始化。
除了从头开始创建一个新的数组之外,APR中还允许使用apr_array_copy将一个数组拷贝到一个新的数组:
APR_DECLARE(apr_array_header_t *) apr_array_copy(apr_pool_t *p,const apr_array_header_t *arr)
Arr是需要拷贝的源数组,拷贝后的数组由函数返回。拷贝函数内部首先定义一个arp_array_header_t的变量res,从内存池p中为其分配足够的空间,然后调用make_array_core生成一个与arr数组大小相同的数组,再调用memcpy逐一进行内存拷贝。然后返回该空间。
3.1.4元素压入和弹出
Apache中对数组元素的操作类似于堆栈,只允许弹出(pop)和压入(push)两种,因此你无法象在C语言中随意的访问数组中的元素。
当数据需要保存到数组中的时候,通过函数apr_array_push函数进行,其原型声明如下:
APR_DECLARE(void *) apr_array_push(apr_array_header_t *arr)
arr是需要保存到数组中的元素。元素的保存按照从左到右,即从低索引到高索引依次存储,不可能出现C语言中的随机保存的情况,因此从这个角度而言,数组称之为堆栈更合适。
在将元素压入数组之前函数首先检查数组中是否有可用的空闲空间;如果有剩余可用空间,其将直接将元素拷贝到第nelts+1数组的位置,调整nelts为nelts++,同时返回该元素。如果没有,即意味着当前数据中nalloc个空间都已经被使用,即nelts=nalloc,那么此时必须扩大数组空间用来保存压入的数据。不过数组空间的增加并不是需要几个就增加几个,而是遵循下面的批量增加原则:
■ 如果压入数据之前nalloc为0,即尚未分配任何空间,那么此时只创建大小为elt_size的空间,即一个元素的空间。
■ 如果当前元素压入之前,系统分配的nalloc个单元都已经被使用完毕,那么此时将直接批量一次性将空间扩大到nalloc*2个元素空间。
一旦分配完这些空间,第一个可用的空闲空间则是第nalloc+1个元素。此时只需要将需要压入的元素拷贝到该地址空间即可,拷贝完之后,将elt_size加一,并返回新元素的地址。
与apr_array_push类似,Apache提供了另外的一个版本的压入函数apr_array_push_noclear,该函数与apr_array_push函数功能基本类似,其唯一区别正如函数名称,在于“noclear”。 apr_array_push在产生新的空闲块,压入新元素之前调用memset对新内存块进行清零操作,而“noclear”函数则省去了这一步。
与元素压入匹配,从数组中取元素通过函数apr_array_pop进行,其函数声明如下:
APR_DECLARE(void *) apr_array_pop(apr_array_header_t *arr)
元素弹出遵循先进先出的弹出原则,因此被弹出的元素永远都是第nelts个,除非当前的数组为空,不在有任何的有效数据。返回语句可以简化为return arr->elts + (arr->elt_size * (--arr->nelts));
3.1.5数组合并
Apache中使用apr_array_cat将两个元素进行合并,函数定义如下:
APR_DECLARE(void) apr_array_cat(apr_array_header_t *dst,const apr_array_header_t *src)
函数将数组src添加到数组dst的末尾。函数首先检查当前的空闲单元能不能容下src数组,这里容纳的概念并不是容纳src中的nalloc个元素,而仅仅是容纳下src中的nelts个非空闲单元,并不包括nalloc-nelts空闲单元,因此函数需要比较的是(dst->nalloc) - (dst->nelts) >= (src->nelts),而不是(dst->nalloc) - (dst->nelts) >= (src->nalloc)。如果能够容纳,则没有必要分配新的空间,直接内存拷贝就可以了。
如果dst中所有的空闲空单元都不够存放src中的空闲单元,那么此时毫无疑问dst需要分配新的空间,分配算法如下:
1)、如果dst中元素个数为零,此时,将产生一个新的空间。
2)、如果dst中元素个数nalloc不为零,则首先产生nalloc*2个空闲空间。
3)、尽管如此,如果src的非空闲元素实在太多,而dst本身空闲空间很小,那么即使一次产生 nalloc个空闲块也不一定能够盛放src中的元素。唯一的办法就是不停的产生新的空闲块,每次产生后的总块数都是当前的一倍,直到空闲块总数能够容纳src中的非空闲元素为止。这真是下面的代码所做的事情:
if (dst->nelts + src->nelts > dst->nalloc) {
int new_size = (dst->nalloc <= 0) ? 1 : dst->nalloc * 2;
while (dst->nelts + src->nelts > new_size) {
new_size *= 2;
}
}
一旦确定确定需要产生的空闲块的总数,函数将一次性从内存池dst->pool中申请。然后将src中的数据拷贝空间空间即可。

关于作者
张中庆,目前主要的研究方向是嵌入式浏览器,移动中间件以及大规模服务器设计。目前正在进行Apache的源代码分析,计划出版《Apache源代码全景分析》上下册。Apache系列文章为本书的草案部分,对Apache感兴趣的朋友可以通过flydish1234 at sina.com.cn与之联系!

如果你觉得本文不错,请点击文后的“推荐本文”链接!!
分享到:
评论

相关推荐

    commons-math3-3.6.1-API文档中文版

    math3是Apache下的一款进行数学计算的一款java开源工具。 math3是一款非常好用的工具,里面提供了各种运算的方法及类,方便大家调用。 apache-commons-math3是java的一种科学计算类库,实现科学计算功能的类库其他...

    python数据分析随书代码

    8.8 Apache Cassandra 197 8.9 小结 201 第9章 分析文本数据和社交媒体 203 9.1 安装NLTK 203 9.2 滤除停用字、姓名和数字 206 9.3 词袋模型 208 9.4 词频分析 209 9.5 朴素贝叶斯分类 211 9.6 情感分析 214...

    PHP二维索引数组的遍历实例分析【2种方式】

    本文实例讲述了PHP二维索引数组的遍历。... array(2,'洛某','B公司','上海市','(021)123456789','lm@apache.com'),//子数组2 array(3,'峰某','C公司','天津市','(022)24680246','fm@mysql.com'), //子数组3 a

    Apache TVM 是一个开放源代码的机器学习编译器框架,用于 CPU,GPU 和机器学习加速器.zip

    它可以是从数组到完整数据库的任何内容。 通过查看数据库,我们可以看到最受欢迎的颜色是白色,最老的车龄是 17 年,但是如果仅通过查看其他值就可以预测汽车是否具有 AutoPass,该怎么办? 这就是机器学习的目的!...

    试验2-2shell简介

    linux入门学习最好的课件!!!! 试验1安装和初步使用 试验2-1linux常用命令 试验2-2shell简介 试验3文件系统管理 试验4-1用户和组的管理 试验4-2进程管理 试验5linux-apache 试验6linux-DHCP 实验7linux-DNS

    数据结构与算法分析_Java语言描述(第2版)]

    中文名: 数据结构与算法分析_Java语言描述(第2版)作者: 韦斯译者: 冯舜玺资源格式: PDF版本: 扫描版出版社: 机械工业出版社书号: ISBN:9787111231837发行时间: 2009年01月01日地区: 大陆语言: 简体中文简介: 内容...

    精通正则表达式基于.NET ASP PHP JSP JavaScript

    Apache日志分析.php Apache日志分析 第17章(/17/) JSPExample1.jsp JSP页面中整型数据的使用 JSPExample2.jsp JSP页面中循环输出整型数据 JSPExample3.jsp 计算一光年的距离 ...

    史上最全韩顺平传智播客PHP就业班视频,10月份全集

    预定义超全局数组①-原理分析 $_GET 9-17 5.预定义超全局数组②-$_POST $_REQUEST 9-17 6.预定义超全局数组③-$_SERVER $_ENV $GLOBALS 9-17 7.zend studio使用 项目开发五个阶段 雇员管理系统① 9-19 1.回顾 9-19 2...

    (全)传智播客PHP就业班视频完整课程

    预定义超全局数组①-原理分析 $_GET 9-17 5.预定义超全局数组②-$_POST $_REQUEST 9-17 6.预定义超全局数组③-$_SERVER $_ENV $GLOBALS 9-17 7.zend studio使用 项目开发五个阶段 雇员管理系统① 9-19 1.回顾 9-19 2...

    史上最全传智播客PHP就业班视频课,8月份视频

    预定义超全局数组①-原理分析 $_GET 9-17 5.预定义超全局数组②-$_POST $_REQUEST 9-17 6.预定义超全局数组③-$_SERVER $_ENV $GLOBALS 9-17 7.zend studio使用 项目开发五个阶段 雇员管理系统① 9-19 1.回顾 9-19 2...

    韩顺平PHP JS JQUERY 所有视频下载种子 货真价实

    预定义超全局数组①-原理分析 $_GET 9-17 5.预定义超全局数组②-$_POST $_REQUEST 9-17 6.预定义超全局数组③-$_SERVER $_ENV $GLOBALS 9-17 7.zend studio使用 项目开发五个阶段 雇员管理系统① 9-19 1.回顾 9-19 2...

    PHP入门到精通

    27.1系统分析 27.2系统设计 27.3软件开发环境 27.4数据库与数据表设计 27.5搭建系统框架 27.6公共文件设计 27.7前台首页设计 27.8登录模块设计 27.9会员信息模块设计 27.10商品显示模块设计 27.11购物车模块设计 27....

    PHP入门到精通02

    27.1系统分析 27.2系统设计 27.3软件开发环境 27.4数据库与数据表设计 27.5搭建系统框架 27.6公共文件设计 27.7前台首页设计 27.8登录模块设计 27.9会员信息模块设计 27.10商品显示模块设计 27.11购物车模块设计 27....

    史上最全韩顺平传智播客PHP就业班视频,9月份全集

    预定义超全局数组①-原理分析 $_GET 9-17 5.预定义超全局数组②-$_POST $_REQUEST 9-17 6.预定义超全局数组③-$_SERVER $_ENV $GLOBALS 9-17 7.zend studio使用 项目开发五个阶段 雇员管理系统① 9-19 1.回顾 9-19 2...

    Java连接数据库的综合类

    Apache提供的一个对JDBC进行简单封装的开源工具类库, 它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。 二、为什么需要Dbutils ? 在使用Dbutils 之前,我们Dao层使用的技术是JDBC,那么分析一下JDBC的...

    matlab小动物图形代码-Remote_sensing-GIS:遥感GIS

    matlab小动物图形代码很棒的地理空间 一长串的地理空间分析工具。 地理空间分析,或仅仅是空间分析,是一种将统计分析和其他分析...-数组数据库,允许存储和查询大规模多维数组,例如出现在地球,太空和生命科学等领

    matlab小动物图形代码--Awesome-Geospatial:一长串的地理空间工具和资源

    matlab小动物图形代码很棒的地理空间 一长串的地理空间分析工具。 地理空间分析,或仅仅是空间分析,是一种将统计分析和其他分析...-数组数据库,允许存储和查询大规模多维数组,例如出现在地球,太空和生命科学等领

    PHP基础教程-推荐教

    6.超全局变量数组 41 7.数据类型 43 8.运算符 47 9.函数 48 10.session的应用 51 第二节 PHP编程要点 53 1.流程控制结构 53 2. PHP嵌入HTML或JavaScript中 54 3.用PHP输出HTML或JavaScript 55 4.自服务程序 56 第三...

    PHP基础教程-推荐

    6.超全局变量数组 41 7.数据类型 43 8.运算符 47 9.函数 48 10.session的应用 51 第二节 PHP编程要点 53 1.流程控制结构 53 2. PHP嵌入HTML或JavaScript中 53 3.用PHP输出HTML或JavaScript 55 4.自服务程序 56 第三...

    myTomcat:WebServer + Tomcat源码分析总结

    来自《深入剖析Tomcat》 ...前导工作: org.apache.catalina.startup.Bootstrap启动startup.sh/...StandardServer的初始化(),start()方法调用所有的服务组件(数组)StandardService的初始化(),start()方法,

Global site tag (gtag.js) - Google Analytics