rt-thread-0.24内核的一些疑问
rt_err_t rt_thread_init(struct rt_thread* thread,const char* name,
void (*entry)(void* parameter), void* parameter,
void* stack_start, rt_uint32_t stack_size,
rt_uint8_t priority, rt_uint32_t tick)
{
/* thread check */
RT_ASSERT(thread != RT_NULL);
RT_ASSERT(stack_start != RT_NULL);
/* init thread object */
rt_object_init((rt_object_t)thread, RT_Object_Class_Thread, name);
return _rt_thread_init(thread, name, entry, parameter,
stack_start, stack_size,
priority, tick);
}
其中调用了rt_object_init((rt_object_t)thread, RT_Object_Class_Thread, name);
这个rt_object_t 结构体类型和rt_thread* thread结构体类型完全不同,怎么可以随意转换
然后在rt_object_init中
void rt_object_init(struct rt_object* object, enum rt_object_class_type type, const char* name)
{
register rt_base_t temp;
struct rt_object_information* information;
/* get object information */
information = &rt_object_container;
/* init object's parameters */
/* set object type to static */
object->type = type | RT_Object_Class_Static;
/* copy name */
for (temp = 0; temp < RT_NAME_MAX; temp ++)
{
object->name = name;
}
#ifdef RT_USING_HOOK
if (rt_object_attach_hook != RT_NULL)
{
rt_object_attach_hook(object);
}
#endif
/* lock interrupt */
temp = rt_hw_interrupt_disable();
/* insert object into information object list */
rt_list_insert_after(&(information->object_list), &(object->list));
/* unlock interrupt */
rt_hw_interrupt_enable(temp);
}
这个object结构体随意使用,
/* set object type to static */
object->type = type | RT_Object_Class_Static;
/* copy name */
for (temp = 0; temp < RT_NAME_MAX; temp ++)
{
object->name = name;
}
C语言还可以怎么干吗?我甚为疑惑
还有那个/* get object information */
information = &rt_object_container;
这个rt_object_container定义怎么看得我一头雾水
这个枚举量中enum rt_object_class_typ也没有给出那个 RT_Object_Class_Timer, /* The object is a timer. */
RT_Object_Class_Unknown, /* The object is unknown. */
具体数值来
究竟是在那儿定义的
VIM+CTAGS根本就找不到
ffxz麻烦答一下疑? 附加说一句,
那个文档实在太"简单"了。
最基本的你也要把内核的几个链表是干什么用的,thread块初始化时如何完成的,还有那些object的作用讲清楚吧。
如果你不愿意讲,好歹也要到代码中注释一下吧。
看得实在令人难受。 我觉得rt-thread的对象处理相当好,可谓其特色之处
在rt-thread中,各种类型的结构抽象成一个对象,同一类型的结构做成一个链表,统一归内核管理 不错,从架构上来讲,RT-Thread可以看作是基于对象架构的RTOS,基于对象架构的主要特点是封装,继承与多态。这样架构的好处在于对系统的抽象和描述性更好,使得系统易于管理,并且具有很强的扩展特性,RT-Thread中可以自由的配置,裁剪各个对象模块,如线程内通信模块mailbox对象,semphore对象,其他如device对象等都可以通过配置裁剪来满足特定需求。
一般来说,C++更适合对象系统的开发,但C++不适合像RTOS这类需要精确控制的系统,所以,在RT-Thread用C语言实现了一套精简内核对象系统,实现对象特性的子集如封装,继承和多态。
例如RT-Thread的所有内核对象都是由基对象继承而来,mailbox,semphore,mutex对象都是由ipc对象继承而来,拥有共同的ipc对象的方法。在设备管理系统中,则用到了多态的一些特性。
这是本人对RT-Thread对象内核架构的一点理解,ffxz兄解释的应该会更专业。 这个就是C语言风格面向对象编程的特点了,
先看看struct rt_thread结构体:
struct rt_thread
{
/* rt object */
char name; /* the name of thread */
rt_uint8_ttype; /* type of object */
rt_uint8_tflags; /* thread's flags */
rt_list_t list; /* the object list */
rt_thread_t tid; /* the thread id */
rt_list_t tlist; /* the thread list */
/* stack point and entry */
void* sp; /* stack point */
void* entry; /* entry */
void* parameter; /* parameter */
void* stack_addr; /* stack address */
rt_uint16_t stack_size; /* stack size */
/* error code */
rt_err_t error; /* error code */
...
};
再看看struct rt_object结构体:
struct rt_object
{
/* name of kernel object */
char name;
/* type of kernel object */
rt_uint8_t type;
/* flag of kernel object */
rt_uint8_t flag;
/* list pointer of kernel object */
rt_list_tlist;
};
即rt_thread结构体的前半部分是完全包含rt_object结构体的,那么最终结构体数据在内存中的布局也是
name
type
flag
list
这样的布局,和rt_object结构体在内存中的布局是完全一致的。
所以当把一个rt_thread指针类型转换到rt_object指针类型时,前半部分的数据访问将完全按照rt_object的方式进行,通过这种方式也就实现了对象中的基本继承关系。在RT-Thread中,也就rt_thread结构体的定义特殊些,实际上也是完全可以写成:
struct rt_thread
{
/* inherit from object */
struct rt_object parent;
rt_thread_t tid; /* the thread id */
rt_list_t tlist; /* the thread list */
/* stack point and entry */
void* sp; /* stack point */
void* entry; /* entry */
void* parameter; /* parameter */
void* stack_addr; /* stack address */
rt_uint16_t stack_size; /* stack size */
...
};
这个是RT-Thread中其他几种对象的写法,代表了这个类型从rt_object派生而来。
例如代码:(假设tid指针非空)
struct rt_thread* tid;
struct rt_object* obj;
/* 子类转换为父类(抽象类) */
obj = (struct rt_object*)tid;
obj指针实际上指向的是&(tid->parent),obj指针就可以操作tid->parent里的内容了。
--------
正如shaolin所说,RT-Thread内部是有一套基本的对象机制,为了保持这套对象机制的简洁性有些对象机制是没有完全实现的,而在RTGUI中则实现了对象中的运行时类型识别(RTTI)。 文档上真是很抱歉,由于最近比较忙,所以本来说尽快给出一份完整些的文档,但一直还没拿出来。目前RT-Thread还依赖于业余时间来完成&完善,所以还请多担待。 为什么会存在动态创建和静态创建任务这两种机制呢,
向那个shell调用的hello是动态创建的吧,这些动态创建意义何在
难道是想外部传一个程序进来,然后可以运行?? "shell调用的hello" 这个是直接函数调用,不是动态创建
动态创建的意义在于,线程的TCB,栈空间只在运行期分配给线程,线程运行结束后自动收回。
而在运行期,动态线程和静态线程是完全一样的,没有什么区别。
执行外部(放在FAT或NFS文件系统上)程序,这块在RT-Thread中叫做动态模块加载,加载过后就有些类似于常见的应用程序,当它运行结束会把它运行期间创建的对象全部释放,内存也做相应回收。和常见的应用程序差别则是,它依然运行于OS的线性内存空间,实时性不会受到任何影响(像Linux以前就存在应用程序到内核态的不可抢占问题,应用态到核心态的切换问题等,而RT-Thread的动态模块加载则不受影响)。目前这部分代码还未发布出来。 回楼上,线程的意思我看明白了。
如何实现这些动态模块,这是一个问题吧
首先要满足二进制的代码写到外部存储器上,然后运行一个shell,到存储器上找这些代码。
然后运行起来。
关键是你如何让编译器编译出能在你的平台上加载的代码,
这个也太难了。
因为你运行的不是一个bootloader,而是一个内核。
想法很好
期待继续 一般来说,外部存储器上可以保存由编译器生成的位置无关的elf文件,需要加载模块时,把这个elf文件从存储器读到内存中,分别解析elf文件相应的段,并给各个段分配相应的物理空间,对elf文件中未引用的符号进行重链接,然后创建一个动态任务来执行这个elf对应的程序段,基本过程是可以这样做的,难点在于资源的分配和管理。 用GCC基本都可以生成相应的代码,而RealView Compiler暂时只能支持ARM指令,对于Cortex-M3一类的thumb2指令还不能支持。
使用这种方式还有一个好处,如果用户代码不操作硬件及硬件上的固定地址,那么编译好的用户程序可以在相同结构上的RT-Thread运行,例如AT91SAM7X256下的用户程序可以二进制兼容在LPC2148上运行。
动态模块加载是RT-Thread中一个非常重要的特性,发布的点大约在0.3.0 - 0.4.0之间。 如果能做到9楼所说的,那没什么疑问了。
elf文件执行位置与位置无关。
这么来说还是要一个类似shell的东西,告诉内核需要运行哪个elf
然后内核里面还得有这个解析elf的东西,
然后分配相应的堆栈和优先级以及其他资源,这个问题好像不是很大,可以通过文件名或者编译在文件内部某个固定地址处。
运行完毕执行某个命令回收这些资源就行了。
听起来很不错 shaolin是RT-Thread中一位非常重要的开发成员,所以确实如shaolin所说。shell可有可无,采用图形界面方式也能够“执行应用程序”;采用web方式也能够指定cgi-bin的位置。 web方式还不如弄过远程的ssh或者telnet
再来一个小的shell,这不就是一个精简版的实时系统么 对象处理的方法和Keil的RTX很相似,
当初看到RTX中将TCB类型转换后传入统一的链表处理函数中时,很是欣赏,
原来 RT-Thread 早就有了,看来自己是落伍了 ssh还是算了 SSL太恐怖了 那个FINSH应该可以取代telnet吧??
页:
[1]