SOD设计思想

struct oriented design,
是介于procedure oriented design 和 object oriented design之间的一种设计思想。
在POD的基础上,借用了OOD的很多理念。
与OOD不同的是,SOD存在大量的FunctionEntryPoint。体现为系统提供了大量的API。也就是说,可以直接硬链接API,这是基于LabelMark实现的,所以是静态流程入口(Fixed Procedure),同时,SOD中,又使用了函数指针,把对象相关的函数封装到结构体对象中去,当系统发生函数调用时,通过对象指针索引到对应函数指针,来产生对应的函数调用。这是基于InstanceRegister实现的,所以是动态流程入口(Dynamic Procedure)。
再看看调用栈,为了更容易和通常所提到的分层架构中的上层和下层对应,我们约定一个新的概念,上游调用和下游调用。新生长的调用,在调用栈中为下游调用,对应于分层架构中的下层,而更靠近调用栈起点的调用,在调用栈中为上游调用,对应于分层架构中的上层。
为了能够实现良好的移植性,适应更多的平台或者应用场合,往往需要把一个调用栈进行合理抽取,形成更合理的流程(procedure),将通用的处理部分设计成固定流程,放置在上游调用的位置,而将平台相关的部分或者应用相关的部分,放置在下游调用的位置。实现流程统一,但是操作各异的目的。

有几个相关的概念。
1)struct object,结构体对象,它用来将一个模块所需要用的到相关数据,整合在一起,一个模块内的相关API,都将使用结构体对象作为传入参数。
2)data element,数据元素,它是一个具体的数据,例如char int long等,它用来存放实际的数据,而不是用来存放指针。
3)entry ejector,入口弹射器,它是一个函数指针,它用来指向某个FunctionEntry,所以这个指针有个专有名词,称为入口弹射器,表明它的作用。
4)instance tag,实体标签,它是一个数据指针,它用来指向某个结构体对象,所以这个指针有个专有名词,称为实体标签,表明它的作用。
5)EAPI,exported application programming interface,它是导出的函数,是TextCode,它在使用时,是被硬链接的,即,其他部分在使用EAPI时,是基于LabelMark的,直接使用函数名称来调用函数。
6)Callback,回调函数,它也是TextCode,Callback是在使用是,是被动态链接的,即,其他部分在使用Callback时,是基于InstanceRegister的,它不能直接使用函数名称来调用函数,而应该使用EntryEjector来间接跳转。所以,Callback在使用前,要先挂接到Ejector,之后才能使用。
7)control panel,控制面板,它是一个struct object,只是,它里面的大部分成员,都是entry ejector。例如,驱动中常见的ops就是一种control panel。
8)RDB,resource description block,资源描述块,它是一个struct object,它的特征是,只包含data element,没有entry ejector。
8)RCB,resource control block,资源控制块,它是一个struct object,它内嵌或者关联着RDB,同时,它还必须内嵌OPS。
当应用程序调用API时,会传入RCB,那么API在自身执行以及后续调用时,都将围绕RCB展开,即,都会传递RCB作为主参数。
各个被调用的函数,从RCB中查找自身运行所需要的数据,从而实现对象统一,成员自取。

SOD的核心,就是设计出合理的struct。
一个struct,由多个不同的member构成,其中有一些,被称为machanism member,而另一些,被称为transaction member。
这类似于驱动中机制性函数和事务性函数的概念。
事务性成员,用来存放业务相关的数据,data element和entry ejector,都是事务性成员。
机制性成员,用来存放机制相关的数据,instance tag是机制性成员,它只有一个作用,就是关联索引。如果从衍生的角度看,instance tag是衍生对象对抽象对象的非内嵌式扩展方式。
实体标签的设计,是struct设计时的关键。在一个复杂的处理机制中,往往需要多个对象协同工作,如何让函数能够利用传入的对象,索引到所需要的具体实例,即衍生对象,就是实体标签的一个重要功能。例如驱动中常见的回溯引用。
以FILE和CDEV为例,当用户调用read或者write时,内核只会传入FILE,而不会传入INODE。而要索引到具体的DerivedCDEV,又只能通过INODE。怎么办?
解决的方法就是open,在open被调用时,内核会传入INODE和FILE,所以open中,是为FILE建立索引到INODE的方法的唯一位置。
这里,FILE中就放置了一个InstanceTag,即FILE->private_data,用来标记DerivedCDEV。
类似的例子还有很多,通常都被命名为private_data。
当一个模块中的不同函数,在不同的执行路径中被调用时,需要从传入的对象中索引到特定的协作对象时,就要用到这个private_data。
如果对象A和对象B,在逻辑上存在固定的关联关系,那么显然,在设计时,就会考虑到并设计好。
如果他们是在运行时才发生协作关系,那么只能通过private_data的形式,在运行时建立关联。

SOD的另一个重要方面,就是设计出合理的EAPI和Callback机制。
用户程序如果想调用模块的服务,只能使用EAPI。而用户程序如果想定制某个处理流程中的某些特定环节,就需要自己设计好Callback,然后利用模块的EAPI提供的服务,将自己定制的Callback挂接到特定的函数接口上。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值