美文网首页
APR分析-设计篇

APR分析-设计篇

作者: 偷风筝的人_ | 来源:发表于2017-12-01 22:02 被阅读0次

APR分析-设计篇

作为一个可移植的运行时环境,APR设计当然是很精妙的,但精妙的同时对使用者有一些限制。

APR附带一个简短的设计文档,文字言简意赅,其中很多的设计思想都值得我们所借鉴,主要从三个方面谈。

1、类型

1) APR提供并建议用户使用APR自定义的数据类型,好处很多,比如便于代码移植,避免数据间进行不必要的类型转换(如果你不使用APR自定义的数据类型,你在使用某些APR提供的接口时,就需要进行一些参数的类型转换);自定义数据类型的名字更加具有自描述性,提高代码可读性。APR提供的基本自定义数据类型包括:

typedef unsigned char  apr_byte_t;

typedef short    apr_int16_t;

typedef unsigned short  apr_uint16_t;

typedef int    apr_int32_t;

typedef unsigned int  apr_uint32_t;

typedef long long   apr_int64_t;

typedef unsigned long long  apr_uint64_t;

这些都是在apr.h中定义的,而apr.h在UNIX平台是通过configure程序生成的,在不同平台APR自定义类型的实际类型是完全有可能不一致的。

2)还有一点值得提的是在APR的设计文档中,它称“dso、mmap、process、thread”等为“base

types”。很难用中文理解之,估计是指apr_mmap_t这些类型吧。权且这么理解吧^_^

3)另外的一个特点就是大多APR类型中都包含一个apr_pool_t类型的字段,该字段用于分配APR内部使用的内存,任何APR函数需要内存都可以通过它分配。如果你创建一个新的类型,你最好在该类型中加入一个apr_pool_t类型的字段,否则所有操作该类型的APR函数都需要一个apr_pool_t类型的参数。

2、函数

1)理解APR的函数设计对阅读APR代码很有帮助。看了APR代码你会发现很多类似APR_DECLARE(apr_hash_t

*) apr_hash_make(apr_pool_t*pool)带APR_DECLARE宏的函数声明,到底是什么意思呢?为什么要加一个APR_DECLARE呢?在apr.h中有这样的解释:“APR的固定个数参数公共函数的声明形式APR_DECLARE(rettype)

apr_func(args);而非固定个数参数的公共函数的声明形式为APR_DECLARE_NONSTD(rettype) apr_func(args, ...);”。在Unix上的apr.h中有这两个宏的定义:

#defineAPR_DECLARE(type)           type

#define APR_DECLARE_NONSTD(type)     type

在apr.h文件中解释了这么做就是为了在不同平台上编译时使用“the most

appropriate calling convention”,这里的“calling convention”是一术语,翻译过来叫“调用约定”。[注1]

常见的调用约定有:stdcall、cdecl、fastcall、thiscall和naked

call,其中cdecl调用约定又称为C调用约定,是C语言缺省的调用约定。

2)如果你想新增APR函数,APR建议你最好能按如下做,这样会和APR提供的函数保持最好的一致性:

a)输出参数为第一个参数;

b)如果某个函数需要内部分配内存,则将一个apr_pool_t参数放在最后。

3、错误处理

大型的系统程序的错误处理是十分重要的,APR作为一通用的库接口集合详细的说明了使用APR时如何进行错误处理。

1)错误处理的第一步就是“错误码和状态码分类”。APR的函数大部分都返回apr_status_t类型的错误码,这是一个int型,在apr_errno.h中定义,和它在一起定义的还有apr所用的所有错误码和状态码。APR定义了5种错误码类型,它们分别为“0”[注2]、APR_OS_START_ERROR、APR_OS_START_STATUS、APR_OS_START_USEERR和APR_OS_START_SYSERR,它们每个都拥有自己独自的偏移量。

2)如何定义错误捕捉策略?

由于APR是可移植的,这样就可能遇到这样一个问题:不同平台错误码的不一致。如何处理呢?APR给我们提供了2种策略:

a)跨多平台返回相同的错误码

这种策略的缺点是转换费时且在转换时有错误码损耗。比如Windows操作系统定义了成百上千错误码,而POSIX才定义了50错误码,如果都转换为规范统一的错误码,势必会有错误码含义丢失,有可能得不到拥有真正含义的错误码。执行流程如:

make syscall that fails

convert to common errorcode

return common errorcode

-------------------------------------------------------------------

decide execution based on common error code

b)返回平台相关错误码,如果需要将它转换为通用错误码

程序的执行路线往往要根据函数返回错误码来定,这么做的缺点就是把这些工作推给了程序员。执行流程如:

make syscall that fails

return error code

-------------------------------------------------------------------

convert to common error code (using ap_canonical_error)

decide execution based on common error code

[注1]调用约定

我们知道函数调用是通过栈操作来完成的,在栈操作过程中需要函数的调用者和被调用者在下面的两个问题上做出协调,达成协议:

a)当参数个数多于一个时,按照什么顺序把参数压入堆栈

b)函数调用后,由谁来把堆栈恢复原来状态

在像C/C++这样的中、高级语言中,使用“调用约定”来说明这两个问题。

[注2]特殊“0”

每个平台都有0,但是都没有实际的定义,0又的确是一个errnovalue的offset,但是它是“匿名的”,它不像EEXIST那样有着可以“自描述”的名字。

相关文章

  • APR分析-设计篇

    APR分析-设计篇 作为一个可移植的运行时环境,APR设计当然是很精妙的,但精妙的同时对使用者有一些限制。 APR...

  • APR分析-高级IO篇

    APR分析-高级IO篇 近两天稍轻闲了些,便抓紧时间学习、学习再学习。在“APR分析-文件IO篇”,我们只分析了最...

  • APR分析-进程篇

    APR分析-进程篇 Apache Server的进程调度一直为人所称道,Apache 2.0推出的APR对进程进行...

  • APR分析-线程篇

    APR分析-线程篇 并行一直是程序设计领域的难点,而线程是并行的一种重要的手段,而且线程的一些特性也能在进程并行时...

  • APR分析-环篇

    APR分析-环篇 APR中少见对数据结构的封装,好像唯一例外的就是其对循环链表,即环(RING)的封装。 在大学的...

  • APR分析-内存篇

    APR分析-内存篇 内存管理一直是让C程序员头痛的问题,作为一个通用接口集,APR当然也提供其自己的内存管理接口-...

  • APR分析信号篇

    APR分析-信号篇 U know信号是Unix的重要系统机制。信号机制使用起来很简单,但是理解起来有并不是那么Ea...

  • APR分析-整体篇

    APR分析-整体篇 由于部门所使用的底层库与Apache Server有着“一定的渊源”,所以总有一种想看看Apa...

  • APR分析-线程同步篇

    APR分析-线程同步篇 在线程同步方面,Posix标准定义了3种同步模型,分别为互斥量、条件变量和读写锁。APR也...

  • APR分析-共享内存篇

    APR分析-共享内存篇 共享内存是一种重要的IPC方式。在项目中多次用到共享内存,只是用而并未深入研究。这次趁研究...

网友评论

      本文标题:APR分析-设计篇

      本文链接:https://www.haomeiwen.com/subject/hfkgbxtx.html