第三章 Apache可移植运行时库
来源:互联网 发布:java同步异步 编辑:程序博客网 时间:2024/05/22 11:46
The Apache Portable Runtime
Apache可移植运行时库(Apache Portable Runtime,APR)和APR的实用库(APR Utilities、APR-UTILS或者APU)是Apache软件基金会旗下两个自主开发和维护的库,为Apache的httpd程序所使用。尽管很多的内核开发者要同时涉及开发httpd(即Web服务器)和APR,然而这两个项目却是相互独立的。APR和APU提供了内核函数,这些函数不仅仅只与Web服务相关,对于更加普遍的应用开发也很有用。
除了Web服务器之外,最有名的APR应用就是Subversion,它是一个版本管理和变更管理系统。另外一个就是Site Valet,一个在网上进行质量保证(QA)和易用性审计的软件套件。Site Valet是由笔者开发的。
本章介绍APR,并探讨如何把APR应用到Apache模块中。本章并没有深入介绍类似于应用程序初始化之类的主题,虽然这些也是必要的,不过它们由Apache内核代码在内部进行处理。对于那些Web服务器内核之外的应用程序开发者,想更深入了解APR可以参考其自身文档,它介绍得很翔实,可以在http://dev.ariel-networks.com/apr/apr-tutorial/ html/ apr-tutorial.html找到APR的教程。
3.1 APR
APR的主要目的是为应用提供一个可移植的、平台无关的层。它使用底层的、交叉平台的库来提供文件系统访问、网络编程、进程和线程管理以及共享内存等功能。那些使用Apache专有APR、而不是使用本地系统功能的模块在平台之间只可以移植的,并且能够在所有被Apache所支持的平台上被干净地(最坏的情况也是需要很小程度修改)编译。
每一个APR模块由一个所有平台共享的应用编程接口(Application Programming Interface,API)和该API所定义的所有函数实现组成。对该API的函数实现基本上(至少一部分)是与平台相关的,尽管这些对于应用程序没有任何影响。
APR的核心就是Apache的资源管理(池),我们将在本章的后面部分进行更加详细的介绍。表3-1列出了APR中的所有模块。
表3-1 APR模块
名称
目的
apr_allocator
内存分配,内部使用
apr_atomic
原子操作
apr_dso
动态加载代码(.so/.dll)
apr_env
读取/设定环境变量
apr_errno
定义错误条件和宏
apr_file_info
文件系统对象和路径的属性
apr_file_io
文件系统输入/输出
apr_fnmatch
文件系统模式匹配
apr_general
初始化/终结,有用的宏
名称
目的
apr_getopt
命令参数
apr_global_mutex
全局锁
apr_hash
哈希表
apr_inherit
文件句柄继承助手
apr_lib
奇数和末端
apr_mmap
内存映射
apr_network_io
网络输入/输出(套接字)
apr_poll
投票
apr_pools
资源管理
apr_portable
APR到本地映射转换
apr_proc_mutex
进程锁
apr_random
随机数
apr_ring
环数据结构和宏
apr_shm
共享内存
apr_signal
信号处理
apr_strings
字符串操作
apr_support
内部支持函数
apr_tables
表格和数组函数
apr_thread_cond
线程条件
apr_thread_mutex
线程锁
apr_thread_proc
线程和进程函数
apr_thread_rwlock
读写锁
apr_time
时间/日期函数
apr_user
用户和组ID服务
apr_version
APR版本
apr_want
标准头文件支持
3.2 APR实用库
APR实用库(APR-UTIL,或者APU)是APR项目的第二个库。它在APR基础上,使用统一标准的编程接口,提供了一部分功能函数集。APU并不是每在一个平台上都有一个单独的模块,但是它为某些其他常用的资源例如数据库提供了一个类似的方法。
表3-2列出了APU的所有模块。
表3-2 APU模块
名称
目的
apr_anylock
透明的、任何锁的封装
apr_base64
Base-64编码
apr_buckets
Buckets/Bucket brigade
apr_date
时间字符串解析
apr_dbd
针对SQL数据库的常用API
apr_dbm
针对DBM数据库的常用API
apr_hooks
钩子实现宏
apr_ldap
LDAP授权API
apr_ldap_init
LDAP初始化API,主要应用在和LDAP服务器的初始安全连接
apr_ldap_option
设置LDAP选项的API
apr_ldap_url
解析和处理LDAP URL的API
apr_md4
MD4编码
apr_md5
MD5编码
apr_optional
可选函数
apr_optional_hooks
可选钩子
apr_queue
线程安全的FIFO队列
apr_reslist
资源池
apr_rmm
可再定位地址的内存
名称
目的
apr_sdbm
SDBM库
apr_sha1
SHA1编码
apr_strmatch
字符串模式匹配
apr_uri
URI解析/构造
apr_uuid
用户标识
apr_xlate
字符集转换(I18N)
apr_xml
XML解析
3.3 基本的约定
APR和APR-UTIL采用了一些约定,使得它们的API具有同质性,并且易于使用。
3.3.1 参考手册:API文档和Doxygen
APR和APU在代码层都有非常好的文档。每一个公开函数和数据类型都在定义它们的头文件中进行了注释,使用了doxygen 友好的格式。那些头文件,或者doxygen生成的文档,为程序员提供了完整的API参考手册。如果你安装了doxygen,那么就可以通过make dox命令从源代码中生成你自己版本的APR参考手册。
3.3.2 命名空间
所有的APR和APU的公开接口都使用了字符串前缀“apr_”(数据类型和函数)和“APR_”(宏),这就为APR定义了一个“保留”的命名空间。
在APR命名空间中,绝大部分的APR和APU模块使用了二级命名空间。这个约定通常基于正在讨论的那个模块的名字。例如,模块apr_dbd中的所有函数使用字符串“apr_dbd_”前缀。有时候使用一个明显的描述性的二级命名空间。例如,在模块apr_network_io中套接字操作使用“apr_socket_”前缀。
3.3.3 声明的宏
APR和APU的公开函数使用类似于APR_DECLARE、APU_DECLARE和APR_ DECLARE_NONSTD的宏进行声明。例如:
APR_DECLARE(apr_status_t) apr_initialize(void);
在很多的平台上,这是一个空声明,并且扩展为
apr_status_t apr_initialize(void);
例如在Windows的Visual C++平台上,需要使用它们自己的、非标准的关键字,例如“_dllexport”来允许其他的模块使用一个函数,这些宏就需要扩展以适应这些需要的关键字。
3.3.4 apr_status_t和返回值
在APR和APU中广泛采用的一个约定是:函数返回一个状态值,用来为调用者指示成功或者是返回一个错误代码。这个类型是apr_status_t,在apr_errno.h中定义,并赋予整数值。因此一个APR函数的常见原型就是:
APR_DECLARE(apr_status_t) apr_do_something(…function args…);
返回值应当在逻辑上进行判断,并且实现一个错误处理函数(进行回复或者对错误进行进一步的描述)。返回值APR_SUCCESS意味着成功,我们通常可以用如下的方式进行错误处理结构:
apr_status_t rv;
...
rv = apr_do_something(... args ...);
if (rv != APR_SUCCESS) {
/* 记录一个错误 */
return rv;
}
有时候我们可能需要做得更多。例如,如果do_something是一个非闭塞的I/O操作并且返回APR_EAGAIN,我们可能需要重试这个操作。
有些函数返回一个字符串(char *或者const char *)、一个void *或者void。这些函数就被认为在没有失败条件或者在错误发生时返回一个空指针。
3.3.5 条件编译
本质上说,APR的一些特色可能并不是每个平台都支持的。例如,FreeBSD在5.x版本之前并没有适合Apache的本地线程实现,因此线程在APR中就不被支持(除非编译时手动设置相应的操作)。
为了在这种情况下应用程序依然能够工作,APR为这些情况提供了APR_HAS_*宏。如果一个应用处于这种情况,它应当使用这些宏进行条件编译。例如,一个模块执行了一个操作,这个操作可能导致在多线程环境下的竞争条件,那么它就可能使用以下的方式。
#if APR_HAS_THREADS
rv = apr_thread_mutex_lock(mutex);
if (rv != APR_SUCCESS) {
/* 记录一个错误 */
/* 放弃关键的操作*/
}
#endif
/* ... 在这里执行关键代码... */
#if APR_HAS_THREAD
apr_thread_mutex_unlock(mutex);
#endif
- 第三章 Apache可移植运行时库
- Apache APR可移植运行库简介
- Apache APR可移植运行库
- Apache APR可移植运行库简介(1)
- Apache APR可移植运行库简介(2)
- Apache APR可移植运行库简介(3)
- Apache APR可移植运行库简介(4)
- Apache APR可移植运行库简介(3)
- Apache APR可移植运行库简介(1)
- Apache APR可移植运行库简介(2)
- Apache APR可移植运行库简介(3)
- Apache APR可移植运行库简介(4)
- Apache APR可移植运行库简介1-4
- 第3章 Apache可移植运行期库《The Apache Modules Book Application Development with Apache》
- APUE中文第三版11章读写锁的一个可运行的例子
- 将可运行程序包移植到ros下
- android移植第三方库
- arm第三方库移植
- pthread_clean_push和pthread_clean_up
- Google Analytics与百度统计原理
- 我的脚步追不上时间的脚步!
- Combo Box CListCtrl 备忘录
- js切换光标
- 第三章 Apache可移植运行时库
- how
- 让运行着的ASP.NET Web程序重新启动
- Ubuntu12.04LTS 安装 eclipse
- Android 系统 root 破解原理分析
- CUDA入门:runtime API创建CUDA程序
- Android Wi-Fi Display(Miracast)介绍
- Linux搭建NTP时间服务器
- android的selector,背景选择器