eCos内核API与内核实现的衔接

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了eCos内核API与内核实现的衔接相关的知识,希望对你有一定的参考价值。


mingdu.zheng <at> gmail <dot> com

 

eCos内核API是以C函数以及C结构体的形式提供的,eCos的内核是使用C++类实现的, ​​kernel/.../src/common/kapi.cxx​​ 将C++类实现衔接到C函数及C结构体,实现C和C++衔接的秘诀在于重构new操作符, new操作符重载的注释称之为 Magic new function,确实挺Magic的。

 

new操作符重载(​​kernel/.../src/common/kapi.cxx:82​​)

inline void *operator new(size_t size, void *ptr)

CYG_CHECK_DATA_PTR( ptr, "Bad pointer" );
return ptr;

这个神奇函数的实现看起来一点都不神奇,仅仅是将它的第二个参数照搬返回。 new操作符的第一个函数总是被new对象的大小,这里的第二个参数 ptr 是重载附加的。 常规的new实现将会在这里调用malloc函数分配内存空间,然后返回malloc分配的内存空间指针。 仅仅观察这个神奇函数的本身并看不出它的神奇之处,再看看对它的引用吧,以比较简单的互斥量为例。

互斥量初始化函数(​​kernel/.../src/common/kapi.cxx:1050​​)

externC void cyg_mutex_init(
cyg_mutex_t *mutex /* Mutex to init */
) __THROW

CYG_ASSERT_SIZES( cyg_mutex_t, Cyg_Mutex );

Cyg_Mutex *m = new((void *)mutex) Cyg_Mutex;

m=m;

应用程序在调用cyg_mutex_init前,首先定义一个全局的cyg_mutex_t的结构体,然后将该结构体的地址传递给cyg_mutex_init函数。 也就是说,mutex指针指向一块内存,该内存大小等于cyg_mutex_t结构体的大小。 观察cyg_mutex_init函数的第2行代码,这里的new操作符引用的是上面重载过的new操作符,new操作符的第1个参数总是size而且是自动传入的, 就像C++类成员函数的this参数一样,第2个参数,也就是代码中的第1个参数是指向cyg_mutex_t的指针,再回顾一下重载的new操作符代码, 你看出来了吗?新建的Cyg_Mutex类实例被存储在传入的cyg_mutex_t结构体实例的存储空间内,也就是说Cyg_Mutex实例和cyg_mutex_t实例是重叠的, 我怀疑我是否已经解释清楚,但是我只能解释到这里啦。然后再看这个函数的第1行代码,这行代码检查cyg_mutex_t类型和Cyg_Mutex类型的大小是否一致, 这是必须的,如果Cyg_Mutex类型所需的存储空间比cyg_mutex_t类型多显然会产生内存破坏,不仅大小要一致,连对应的成员变量排列次序都要求是一致的, 但是没有办法让编译器检查两个类型的成员变量排列次序。 可以查看Cyg_Mutex类定义(​​kernel/.../include/mutex.hxx:66​​​)和cyg_mutex_t结构体定义 (​​kernel/.../include/kapidata.h:515​​)手动检查一下这两个类型的成员变量排列次序。

互斥量加锁函数(​​kernel/.../src/common/kapi.cxx:1066​​)

externC cyg_bool_t cyg_mutex_lock( cyg_mutex_t *mutex ) __THROW

return ((Cyg_Mutex *)mutex)->lock();

API传入的是cyg_mutex_t结构体指针,将这个指针转换成Cyg_Mutex类指针, 然后使用该Cyg_Mutex类指针引用Cyg_Mutex类成员函数实现具体的加锁。

 

以上是关于eCos内核API与内核实现的衔接的主要内容,如果未能解决你的问题,请参考以下文章

在ecos kernel中加函数怎么在上层可以使用

《linux内核设计与实现》第五章

《Linux内核设计与实现》第5章读书整理

内核级HOOK的几种实现与应用

Linux内核与内核函数与操作系统,系统调用,这几者的联系是什么?

HDC2021技术分论坛:HarmonyOS内核技术大揭秘!