vxworks源码剖析-对象篇(转)

当第一次看到vxworks的源码时,我才真正明白了怎么用C语言来实现面向对象的功能;以前虽然遇到过类似的文章,不过总是没有动力去了解实际的原理,这次闲来无事,拿到vxworks的源码,才看出一些端倪。

用c语言实现面向对象,其实是蛮难的,毕竟c语言是纯面向过程的语言,而面向过程和面向对象是两种完全不同的思想,虽不能说格格不入,但至少共同点甚少。不过,c语言天生具有的两大特性成就了其实现面向对象的功能,这就是结构体和指针。熟悉面向对象的朋友都应该知道类和结构体的异同,两者其实是很类似的,甚至可以 这样说,类就是在结构体的基础上衍生而来的,有了结构体后,实现面向对象就不是一句空话。大家都知道,类无非由两部分组成,属性和方法。属性就相当于结构体的域,而方法呢,在C语言中,可以用函数指针来实现,这样,类就构成了。

废话少说,看个示例:

typedef struct obj_class /* OBJ_CLASS */
    {
    OBJ_CORE objCore; /* object core of class object */
    struct mem_part *objPartId; /* memory partition to allocate from */
    unsigned objSize; /* 对象大小 */
    unsigned objAllocCnt; /* 已经分配的对象数目 */
    unsigned objFreeCnt; /* 已经释放的对象数目 */
    unsigned objInitCnt; /* 已经初始化的对象数目 */
    unsigned objTerminateCnt;/* 已经终结的对象数目 */
    int   coreOffset; /* offset from object start to objCore*/
    FUNCPTR createRtn; /* object creation routine */
    FUNCPTR initRtn; /* object initialization routine */
    FUNCPTR destroyRtn; /* object destroy routine */
    FUNCPTR showRtn; /* object show routine */
    FUNCPTR instRtn; /* object inst routine */
    } OBJ_CLASS;

上面这个结构体含有8个成员,5个函数指针,就相当于类的8个属性和5个方法;为了更加深入地了解obj_class,有必要说说各个成员的类型,首先来看看OBJ_CORE,这个类型也是一个结构体,它只包含一个类型为obj_class指针的域:

typedef struct obj_core /* OBJ_CORE */
    {
    struct obj_class *pObjClass; /* pointer to object's class */
    } OBJ_CORE;

相信大多数人应该已经猜到了obj_core的作用,如果没猜到也没关系,看到了后面的初始化函数以后相信大家都明白其作用了。接下来是objPartId,它是一个指向mem_part对象的指针,由于mem_part结构体十分复杂,而且后面会专门分析,因此本文暂不分析,大家只要知道这是一个结构体就可以了。最后一个值得说明的类型是FUNCPTR,使用过vxworks编程的朋友对这个类型肯定不会陌生,不过照顾所有人,还是将其定义描述一下:

typedef int   (*FUNCPTR) ();    /* ptr to function returning int */

描述完了obj_core的定义,下面看看与这个结构体相关的几个函数,函数不是很多,主要是对象创建、对象销毁函数,就相当于C++中的构造函数、析构函数一样,虽然对象创建、销毁最终还是调用obj_core结构体中定义的函数指针来实现的,但从这里,也可以看出,毕竟C语言不是面向对象的语言,要完全实现面向对象的功能,还是十分复杂的,需要借助一些辅助类来完成。说了半天,到底这些函数是什么呢?四个函数:classLibInit、classCreate、classInit和classDestroy(暂时未实现),另外还有一些相关的工具类函数这里就不细述了。上述四个函数(其实是三个函数)的关系可以用下图来表示:


classLibInit函数相当于class类的总类,用于初始化一个工具类对象;而classCreate则是实际的创建具体的对象的函数,其完成的工作,主要是两部分:内存分配和成员初始化。内存分配由objAlloc函数来实现,而成员初始化,则由classinit函数来实现。classInit函数就是具体的成员初始化函数,其职责很简单,将提供的参数赋值给obj_class的各个成员就足够了。上面曾经说过obj_core的作用,这里具体描述一下,在描述之前,先看看下面的代码:

STATUS classInit
    (
    OBJ_CLASS   *pObjClass,     /* pointer to object class to initialize */
    unsigned    objectSize,     /* size of object */
    int         coreOffset,     /* offset from objCore to object start */
    FUNCPTR     createRtn,      /* object creation routine */
    FUNCPTR     initRtn,        /* object initialization routine */
    FUNCPTR     destroyRtn      /* object destroy routine */
    )
    {

    /* default memory partition is system partition */

    略

    /* initialize object methods */

   略

    /* initialize class as valid object */

    objCoreInit (&pObjClass->objCore, classClassId);

    return (OK);
    }

void objCoreInit
    (
    OBJ_CORE    *pObjCore,      /* pointer to object core to initialize */
    OBJ_CLASS   *pObjClass      /* pointer to object class */
    )
    {
    pObjCore->pObjClass = pObjClass; /* validate object */
    pObjClass->objInitCnt ++;   /* keep track of object count */
    }
看完上面的代码以后,相应大多数人都会犯迷糊,因为有一个变量还没有介绍,这就是全局变量classClassId:

/* locals */

LOCAL OBJ_CLASS classClass;

/* globals */

CLASS_ID classClassId = &classClass;
从上面的classInit函数可以看出,只要是通过classCreate创建的对象,其objCore值都指向同一个变量,为什么要这样实现呢?这样实现的目的是为了便于实现类的标识。熟悉面向对象的朋友都知道,判断两个对象是否是同一个类太简单了,可以直接用==,或者用equals方法,或者自己定义一个compare方法,或者用getClass方法,但C语言里面比较只有地址值的比较,因此要实现类的标识相对就要困难一些。因此,这里定义了全局变量classClass,只要某个对象(obj_class变量)的objCore和classClass是相等的,那么它的类型就是obj_class(在vxworks中,类似的情形很多,例如标识文件的fpclass也是如此):

#define OBJ_VERIFY(objId,classId)      \
    (                                                                    \
      (          \
      (((OBJ_ID)(objId))->pObjClass == (struct obj_class *)(classId)) || \
       (         \
       ((OBJ_ID)(objId))->pObjClass &&      \
         (((OBJ_ID)(objId))->pObjClass ==                                \
        (CLASS_ID)(((struct obj_class *)(classId))->initRtn))     \
       )         \
      )                                                                  \
        ?                                                                \
            OK                                                           \
        :                                                                \
            (errno = S_objLib_OBJ_ID_ERROR, ERROR)                       \
    )

obj_class结构体是所有其他vxworks结构体最基础的部分,要弄懂vxworks的实现原理,这个结构体及内存分配机制必须明白。vxworks代码十分精致,本人功力有限,仅能分析到这个地步,不过相信只要持续不停地努力,迟早能领悟其精髓。


0
0
0

来自优快云博客:http://blog.youkuaiyun.com/efan_linux/archive/2009/11/13/4804760.aspx

<think>嗯,用户想了解在VxWorks中使用-Xcode-model=large选项相关的问题,可能遇到了配置错误或者编译问题。首先,我需要回忆一下VxWorks的编译模型相关知识。Xcode model通常指代码模型,比如small、large,这会影响指针的大小和内存访问方式。在VxWorks中,代码模型的选择可能会影响应用程序的内存布局和性能。 根据引用[1],VxWorks是微内核结构,内核提供基本功能,所以用户可能需要配置内核参数来支持不同的代码模型。用户提到的-Xcode-model=large可能是在编译时指定的选项,用来选择大代码模型,适用于需要更大地址空间的应用程序。这时候可能需要检查内核配置是否支持大代码模型,比如是否启用了足够的地址空间或者相关的内存管理模块。 另外,引用[4]提到在VxWorks内核配置时遇到错误,Workbench会给出提示。如果用户在使用large代码模型时出现错误,可能需要检查内核配置中是否缺少必要的组件,比如是否启用了大内存支持,或者相关的链接脚本是否正确配置了内存区域。 用户的问题可能涉及编译选项与内核配置的不匹配。例如,使用large代码模型可能需要更大的堆栈空间,或者在链接时需要调整内存分配。此外,代码模型的选择还会影响与第三方库的兼容性,比如引用[2]提到的Qt应用程序,如果Qt库是用不同的代码模型编译的,可能导致链接错误。 可能的解决步骤包括:检查编译选项是否正确,确认内核配置支持large模型,查看错误日志定位具体问题,调整链接脚本或内存分配设置。此外,参考Workbench的错误提示(如引用[4]所述)可以帮助用户找到具体的配置问题,比如缺少某些模块或参数设置不当。 需要提醒用户注意,不同版本的VxWorks可能在代码模型的支持上有所不同,确保文档和版本匹配也很重要。如果问题依然存在,可能需要联系Wind River的支持团队获取专业帮助,或者查找相关的补丁和更新。</think>### 关于VxWorks中`-Xcode-model=large`选项的问题解析 #### 1. 代码模型(Xcode Model)的作用 代码模型决定了编译器如何处理指针和地址范围。`-Xcode-model=large`通常用于需要更大地址空间的应用程序(如涉及大量代码或数据的场景),此时指针使用全32位或64位寻址[^1]。在VxWorks中,若未正确配置内核或工具链,可能引发链接错误或内存分配异常。 #### 2. 常见问题与解决方法 **问题1:编译时出现"relocation truncated to fit"错误** - **原因**:代码模型与内存布局不匹配。例如,`small`模型默认使用短偏移寻址,而`large`模型需要完整地址。 - **解决**: 1. 检查内核配置中是否启用大内存支持(如`INCLUDE_MMU_BASIC`或`VX_VIRTSPACE`相关选项)[^4]。 2. 在链接脚本(`.ld`文件)中扩展内存区域范围,例如: ```ld MEMORY { RAM : ORIGIN = 0x10000, LENGTH = 0x10000000 } ``` **问题2:Workbench报错"Unsupported code model"** - **原因**:工具链或内核版本不支持`large`模型。 - **解决**: 1. 确认VxWorks版本是否支持该选项(如VxWorks 7及更高版本)。 2. 更新Workbench至最新版本,并通过菜单**Help > Check for Updates**获取补丁[^3]。 **问题3:与第三方库(如Qt)兼容性问题** - **原因**:若Qt库使用`small`模型编译,而应用使用`large`模型,可能引发符号冲突。 - **解决**: 1. 重新编译Qt库,添加`-Xcode-model=large`编译选项[^2]。 2. 确保应用与库的ABI(Application Binary Interface)一致。 #### 3. 配置验证步骤 1. **内核配置检查**: 在Workbench中打开工程,导航至**Kernel Configuration**,验证以下选项: - `CODE_DATA_SECTION_OPTIONS`中启用`-Xcode-model=large` - `USER_RESERVED_MEM`保留足够内存空间[^4]。 2. **编译命令示例**: ```makefile CFLAGS += -Xcode-model=large LDFLAGS += -Wl,--defsym,__DEFAULT_CODE_MODEL=large ``` 3. **运行时验证**: 通过`vxWorks`的Shell执行`memShow`命令,确认内存区域分配符合预期。 #### 4. 性能与限制 - **优势**:支持更大代码/数据段,适用于复杂应用(如GUI、大型算法)。 - **劣势**:可能增加内存占用和降低缓存效率,需权衡性能需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值