eCos组件初始化 .
来源:互联网 发布:农村淘宝服务站在哪 编辑:程序博客网 时间:2024/06/06 09:06
eCos组件初始化机制
eCos组件初始化利用了C++静态对象实例初始化的机制。C++对象在初始化时不像C语言中的静态变量那样只是在特定的内存单元写入特定的数值,C++对象在初始化时将会调用该对象类的构造函数来初始化对象。如果C++对象是在函数内声明,那么函数执行到对象的声明处调用类构造函数来初始化对象,如果C++对象在函数外声明,也就是将C++对象声明为全局对象或静态对象,那么编译器会将该对象的初始化代码地址(函数指针)写到名为".ctors"节,普通程序在进入main函数前由操作系统的运行时库调用存储在".ctors"中的函数指针列表来初始化全局或静态C++对象。
eCos应用在编译后同样会将全局或静态C++对象的初始化代码地址写到".ctors"节,在进入用户代码前,eCos HAL将调用cyg_hal_invoke_constructors函数,该函数调用存储在".ctors"节中的初始化代码。
需要注意的一点,".ctors"中存储的是对象初始化代码地址,而不是类构造函数,因为在初始化对象时,不仅要调用构造函数,而且还要给构造函数传入参数,即使是没有参数的默认构造函数也需要传入隐式的this指针。
忽略CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG选项的cyg_hal_invoke_constructors函数,如果配置了CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG选项,那么该函数将更加复杂些。
- extern pfunc __init_array_start__[];
- extern pfunc __init_array_end__[];
- #define CONSTRUCTORS_START (__init_array_start__[0])// ".ctors"的起始地址
- #define CONSTRUCTORS_END (__init_array_end__) // ".ctors"的终止地址
- #define NEXT_CONSTRUCTOR(c) ((c)++)
- void
- cyg_hal_invoke_constructors (void)
- {
- pfunc *p;
- for (p = &CONSTRUCTORS_START; p != CONSTRUCTORS_END; NEXT_CONSTRUCTOR(p))
- (*p)();
- }
extern pfunc __init_array_start__[]; extern pfunc __init_array_end__[]; #define CONSTRUCTORS_START (__init_array_start__[0])// ".ctors"的起始地址#define CONSTRUCTORS_END (__init_array_end__) // ".ctors"的终止地址#define NEXT_CONSTRUCTOR(c) ((c)++)voidcyg_hal_invoke_constructors (void){ pfunc *p; for (p = &CONSTRUCTORS_START; p != CONSTRUCTORS_END; NEXT_CONSTRUCTOR(p)) (*p)();}
C++语言实现的组件初始化
举个例子,每个操作系统都需要一个空闲线程,eCos也不例外,eCos的空闲线程就是以C++全局对象实例初始化机制来创建的。
- Cyg_IdleThread idle_thread[CYGNUM_KERNEL_CPU_MAX] CYG_INIT_PRIORITY( IDLE_THREAD );
- Cyg_IdleThread::Cyg_IdleThread()
- : Cyg_Thread( CYG_THREAD_MIN_PRIORITY,
- idle_thread_main,
- 0,
- (char *)"Idle Thread",
- (CYG_ADDRESS)idle_thread_stack[this-&idle_thread[0]],
- CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE)
- {
- Cyg_Scheduler::scheduler.set_idle_thread( this, this-&idle_thread[0] );
- }
Cyg_IdleThread idle_thread[CYGNUM_KERNEL_CPU_MAX] CYG_INIT_PRIORITY( IDLE_THREAD );Cyg_IdleThread::Cyg_IdleThread() : Cyg_Thread( CYG_THREAD_MIN_PRIORITY, idle_thread_main, 0, (char *)"Idle Thread", (CYG_ADDRESS)idle_thread_stack[this-&idle_thread[0]], CYGNUM_KERNEL_THREADS_IDLE_STACK_SIZE){ Cyg_Scheduler::scheduler.set_idle_thread( this, this-&idle_thread[0] );}
从代码可以看出,eCos的空闲线程Cyg_IdleThread是从常规线程Cyg_Thread继承过来的,除了和常规线程一样的初始化过程外,额外地调用了Cyg_Scheduler::scheduler.set_idle_thread函数,该函数将本线程设置成eCos的空闲线程,并将本线程设置成就绪状态。
C语言实现的组件初始化
如果eCos组件是使用C语言实现的呢?举个例子,IO组件,该组件是使用C语言实现的,但是如果浏览他的源代码,会发现他有一个C++源代码ioinit.cxx,在这个文件中将定义一个C++类,而这个类唯一的作用就是在构造函数中调用cyg_io_init函数,然后声明一个静态的类实例来初始化IO组件。
- externC void cyg_io_init(void);
- class cyg_io_init_class {
- public:
- cyg_io_init_class(void) {
- cyg_io_init();
- }
- };
- static cyg_io_init_class _cyg_io_init CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO);
-
externC void cyg_io_init(void);class cyg_io_init_class {public: cyg_io_init_class(void) { cyg_io_init(); }};static cyg_io_init_class _cyg_io_init CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO);
初始化次序的问题
因为组件之间的依赖关系,初始化过程需要按照一定的次序进行。初始化的次序由CYGBLD_ATTRIB_INIT_PRI宏指定,该宏带有一个参数,该参数数值越小,那么越早调用该实例的初始化代码,例如_cyg_io_init对象的CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO)展开后为__attribute__((init_priority(49000))),而idle_thread对象的宏展开后为__attribute__((init_priority(11100))),由此可以判断空闲线程在IO组件之前被初始化。
检查初始化代码
使用nm和grep可以打印过滤可执行文件的符号列表来检查初始化代码,符号前缀“_GLOBAL__sub_I”表示这是静态对象初始化代码,符号中间部分的数字决定初始化次序,数字后面的部分如果是全局对象,那么是对象标识符,如果是静态变量,与对象的存储位置有关,可能是所在文件名,也可能是对象所在位置后面的全局标识符,反正不是对象标识符,这个有点混乱。
- $ nm app.elf | grep "t _GLOBAL"
- 01001b20 t _GLOBAL__sub_I.10100_diag_write_char
- 01002da0 t _GLOBAL__sub_I.11000_cyg_scheduler_sched_lock
- 01002340 t _GLOBAL__sub_I.11100__ZN18Cyg_HardwareThread12thread_entryEP10Cyg_Thread
- 01002630 t _GLOBAL__sub_I.12000__ZN13Cyg_Interrupt15disable_counterE
- 01005d70 t _GLOBAL__sub_I.14000__ZN9Cyg_Clock15real_time_clockE
- 01006020 t _GLOBAL__sub_I.19900_cygmem_pool_heap1
- 01000050 t _GLOBAL__sub_I.49000_ioinit.cxx
- 010063a0 t _GLOBAL__sub_I.56000__ZN20Cyg_libc_stdio_files5filesE
- 01003290 t _GLOBAL__sub_I.56000_cyg_libc_main_thread
- 01006300 t _GLOBAL__sub_I.56000_cyg_libc_stdio_stdin
- 01003490 t _GLOBAL__sub_I.56001_cyg_libc_stdio_stdout
- 01006260 t _GLOBAL__sub_I.56002_cyg_libc_stdio_stderr
- 01000cc0 t _GLOBAL__sub_I.56100_cyg_iso_c_start
原文见:http://blog.csdn.net/zoomdy/article/details/12754709
- eCos组件初始化
- eCos组件初始化 .
- 为eCos安装扩展组件包
- 为eCos安装扩展组件包 .
- ecos
- ECOS
- eCOS
- ecos
- ECOS
- eCos模块动态加载支持——objloader组件
- 初始化COM组件
- com组件初始化
- COM组件初始化
- 界面初始化组件
- 初始化COM组件
- Flex 组件初始化顺序
- 游戏正在初始化组件
- COM组件初始化
- 浏览器兼容性经典问题(六) text-align的使用
- 动态滚动信息
- ORACLE数据导出到Excel、txt、HTML实用方法
- android usb与自定义HID设备通讯
- VS2008操作PPT
- eCos组件初始化 .
- 网站安全防范工作如何开展
- 《Sparse and Redundant Representations》第七章 平均执行分析 & 第八章 丹选择算法
- Android 隐藏程序的图标
- apache2 add rewrite 增加 rewrite mod_rewrite
- 隐藏 UITabBar
- 超酷透明窗口
- 那些不能错过的XCode插件
- 使用QT遇到问题!