可以看到apache代码中使用了大量的以apr_开头的结构或者函数,这些其实是APR.
什么是apr?
我的理解是apache工作小组在编写apache等C程序过程中所积累的一套编程框架, 里面提供比较先进的内存管理模式和常用的数据结构,另外根据各种平台作了一些不同的宏定义,让代码做到平台无关性。由于做得不错,后来,就干脆把它从apache源代码中脱离出来,又搞了一个项目,apache官方站点上也有它的相关介绍:http://apr.apache.org/
The mission of the Apache Portable Runtime (APR) project is to create and maintain software libraries that provide a predictable and consistent interface to underlying platform-specific implementations. The primary goal is to provide an API to which software developers may code and be assured of predictable if not identical behaviour regardless of the platform on which their software is built, relieving them of the need to code special-case conditions to work around or take advantage of platform-specific deficiencies or features.
apr可以独立于apache安装,让我们编写应用程序时也使用。
有个非常好的英文文档介绍了怎么样使用:http://dev.ariel-networks.com/ap ... l/apr-tutorial.html
上面那个文档非常不错,大家看懂了,我写的这篇就不用看了。
我这个把几个以后经常要用到的介绍一下。
(1) apr_pool_t *pool
内存池,所有的内存操作可以基于这个池之上,当这个池不再需要时,一次性释放该池上的所有内存,这个模式非常适合基于session服务的编程模式, 比如:每个http request都分配一个apr_pool_t,当该http request end时,一次性释放该request运行时申请的所有内存。可以看到struct request_rec中就有这个东东。
用法:
apr_pool_t *mp; apr_pool_create(&mp, NULL); char *buf1; buf1 = apr_palloc(mp, MEM_ALLOC_SIZE); apr_pool_t *mp; apr_pool_create(&mp, NULL); for (i = 0; i < n; ++i) { do_operation(..., mp); apr_pool_clear(mp); } apr_pool_destroy(mp);
(2)数据结构--容器
动态数组---apr_array_header_t
类似于hashmap的apr_table_t:
apr_table_t *tab;
tab = apr_table_make(mp, 5);
apr_table_setn(tab, "foo", "bar");
apr_table_setn(tab, apr_pstrdup(mp, "foo"), apr_pstrdup(mp, "bar"));
const char *v = apr_table_get(tab, "mykey");
可以看到apr_table_t存储key-value pairs类型的数据非常方便,难怪apache所有的http header都用它存储。
其他操作apr_table_t的函数:
APR_DECLARE(const apr_array_header_t *) apr_table_elts(const apr_table_t *t); APR_DECLARE(int) apr_is_empty_table(const apr_table_t *t); APR_DECLARE(int) apr_is_empty_array(const apr_array_header_t *a); APR_DECLARE(apr_array_header_t *) apr_array_make(apr_pool_t *p, int nelts, int elt_size); APR_DECLARE(void *) apr_array_push(apr_array_header_t *arr); APR_DECLARE(void *) apr_array_pop(apr_array_header_t *arr); APR_DECLARE(void) apr_array_cat(apr_array_header_t *dst, const apr_array_header_t *src); APR_DECLARE(apr_array_header_t *) apr_array_copy(apr_pool_t *p, const apr_array_header_t *arr); APR_DECLARE(apr_array_header_t *) apr_array_copy_hdr(apr_pool_t *p, const apr_array_header_t *arr); APR_DECLARE(apr_array_header_t *) apr_array_append(apr_pool_t *p, const apr_array_header_t *first, const apr_array_header_t *second); APR_DECLARE(char *) apr_array_pstrcat(apr_pool_t *p, const apr_array_header_t *arr, const char sep); APR_DECLARE(apr_table_t *) apr_table_make(apr_pool_t *p, int nelts); APR_DECLARE(apr_table_t *) apr_table_copy(apr_pool_t *p, const apr_table_t *t); APR_DECLARE(void) apr_table_clear(apr_table_t *t); APR_DECLARE(const char *) apr_table_get(const apr_table_t *t, const char *key); APR_DECLARE(void) apr_table_set(apr_table_t *t, const char *key, const char *val); APR_DECLARE(void) apr_table_setn(apr_table_t *t, const char *key, const char *val); APR_DECLARE(void) apr_table_unset(apr_table_t *t, const char *key); APR_DECLARE(void) apr_table_merge(apr_table_t *t, const char *key, const char *val); APR_DECLARE(void) apr_table_mergen(apr_table_t *t, const char *key, const char *val); APR_DECLARE(void) apr_table_add(apr_table_t *t, const char *key, const char *val); APR_DECLARE(void) apr_table_addn(apr_table_t *t, const char *key, const char *val); APR_DECLARE(apr_table_t *) apr_table_overlay(apr_pool_t *p, const apr_table_t *overlay, const apr_table_t *base); typedef int (apr_table_do_callback_fn_t)(void *rec, const char *key, const char *value); APR_DECLARE_NONSTD(int) apr_table_do(apr_table_do_callback_fn_t *comp, void *rec, const apr_table_t *t, ...); APR_DECLARE(int) apr_table_vdo(apr_table_do_callback_fn_t *comp, void *rec, const apr_table_t *t, va_list vp); #define APR_OVERLAP_TABLES_SET (0) #define APR_OVERLAP_TABLES_MERGE (1) APR_DECLARE(void) apr_table_overlap(apr_table_t *a, const apr_table_t *b, unsigned flags); APR_DECLARE(void) apr_table_compress(apr_table_t *t, unsigned flags);
其他apr提供的数据结构还有:hash和list,这里不再详述。
(3) 字符串操作
写过C的人都知道,处理字符串是非常头痛的问题,搞不好就内存溢出,apr也提供一些字符串函数,都是基于apr_pool_t, 使用时不用担心内存溢出的问题。
把apr_strings.h贴出来大家一起看看,注释也比较详细,不多说:
APR_DECLARE(int) apr_strnatcmp(char const *a, char const *b); APR_DECLARE(int) apr_strnatcasecmp(char const *a, char const *b); APR_DECLARE(char *) apr_pstrdup(apr_pool_t *p, const char *s); APR_DECLARE(char *) apr_pstrmemdup(apr_pool_t *p, const char *s, apr_size_t n); APR_DECLARE(char *) apr_pstrndup(apr_pool_t *p, const char *s, apr_size_t n); APR_DECLARE(void *) apr_pmemdup(apr_pool_t *p, const void *m, apr_size_t n);