搜索
bottom↓
回复: 15

rt-thread-0.24内核的一些疑问

[复制链接]

出0入0汤圆

发表于 2009-6-13 09:32:18 | 显示全部楼层 |阅读模式
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[type];

        /* 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[temp] = name[temp];
        }

#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[temp] = name[temp];
        }
C语言还可以怎么干吗?我甚为疑惑
还有那个/* get object information */
        information = &rt_object_container[type];
这个rt_object_container[type]定义怎么看得我一头雾水
这个枚举量中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麻烦答一下疑?

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2009-6-13 09:37:41 | 显示全部楼层
附加说一句,
那个文档实在太"简单"了。
最基本的你也要把内核的几个链表是干什么用的,thread块初始化时如何完成的,还有那些object的作用讲清楚吧。
如果你不愿意讲,好歹也要到代码中注释一下吧。
看得实在令人难受。

出0入0汤圆

发表于 2009-6-13 13:38:49 | 显示全部楼层
我觉得rt-thread的对象处理相当好,可谓其特色之处
在rt-thread中,各种类型的结构抽象成一个对象,同一类型的结构做成一个链表,统一归内核管理

出0入0汤圆

发表于 2009-6-13 22:20:01 | 显示全部楼层
不错,从架构上来讲,RT-Thread可以看作是基于对象架构的RTOS,基于对象架构的主要特点是封装,继承与多态。这样架构的好处在于对系统的抽象和描述性更好,使得系统易于管理,并且具有很强的扩展特性,RT-Thread中可以自由的配置,裁剪各个对象模块,如线程内通信模块mailbox对象,semphore对象,其他如device对象等都可以通过配置裁剪来满足特定需求。
一般来说,C++更适合对象系统的开发,但C++不适合像RTOS这类需要精确控制的系统,所以,在RT-Thread用C语言实现了一套精简内核对象系统,实现对象特性的子集如封装,继承和多态。
例如RT-Thread的所有内核对象都是由基对象继承而来,mailbox,semphore,mutex对象都是由ipc对象继承而来,拥有共同的ipc对象的方法。在设备管理系统中,则用到了多态的一些特性。
这是本人对RT-Thread对象内核架构的一点理解,ffxz兄解释的应该会更专业。

出0入0汤圆

发表于 2009-6-13 23:39:07 | 显示全部楼层
这个就是C语言风格面向对象编程的特点了,

先看看struct rt_thread结构体:
struct rt_thread
{
    /* rt object */
    char        name[RT_NAME_MAX];        /* the name of thread */
    rt_uint8_t  type;                     /* type of object */
    rt_uint8_t  flags;                    /* 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[RT_NAME_MAX];
    /* type of kernel object              */
    rt_uint8_t type;
    /* flag of kernel object              */
    rt_uint8_t flag;
    /* list pointer of kernel object      */
    rt_list_t  list;
};

即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)。

出0入0汤圆

发表于 2009-6-13 23:41:22 | 显示全部楼层
文档上真是很抱歉,由于最近比较忙,所以本来说尽快给出一份完整些的文档,但一直还没拿出来。目前RT-Thread还依赖于业余时间来完成&完善,所以还请多担待。

出0入0汤圆

 楼主| 发表于 2009-6-15 18:01:49 | 显示全部楼层
为什么会存在动态创建和静态创建任务这两种机制呢,
向那个shell调用的hello是动态创建的吧,这些动态创建意义何在
难道是想外部传一个程序进来,然后可以运行??

出0入0汤圆

发表于 2009-6-15 18:07:40 | 显示全部楼层
"shell调用的hello" 这个是直接函数调用,不是动态创建

动态创建的意义在于,线程的TCB,栈空间只在运行期分配给线程,线程运行结束后自动收回。

而在运行期,动态线程和静态线程是完全一样的,没有什么区别。

执行外部(放在FAT或NFS文件系统上)程序,这块在RT-Thread中叫做动态模块加载,加载过后就有些类似于常见的应用程序,当它运行结束会把它运行期间创建的对象全部释放,内存也做相应回收。和常见的应用程序差别则是,它依然运行于OS的线性内存空间,实时性不会受到任何影响(像Linux以前就存在应用程序到内核态的不可抢占问题,应用态到核心态的切换问题等,而RT-Thread的动态模块加载则不受影响)。目前这部分代码还未发布出来。

出0入0汤圆

 楼主| 发表于 2009-6-15 22:58:40 | 显示全部楼层
回楼上,线程的意思我看明白了。
如何实现这些动态模块,这是一个问题吧
首先要满足二进制的代码写到外部存储器上,然后运行一个shell,到存储器上找这些代码。
然后运行起来。
关键是你如何让编译器编译出能在你的平台上加载的代码,
这个也太难了。
因为你运行的不是一个bootloader,而是一个内核。
想法很好
期待继续

出0入0汤圆

发表于 2009-6-15 23:14:52 | 显示全部楼层
一般来说,外部存储器上可以保存由编译器生成的位置无关的elf文件,需要加载模块时,把这个elf文件从存储器读到内存中,分别解析elf文件相应的段,并给各个段分配相应的物理空间,对elf文件中未引用的符号进行重链接,然后创建一个动态任务来执行这个elf对应的程序段,基本过程是可以这样做的,难点在于资源的分配和管理。

出0入0汤圆

发表于 2009-6-16 09:22:55 | 显示全部楼层
用GCC基本都可以生成相应的代码,而RealView Compiler暂时只能支持ARM指令,对于Cortex-M3一类的thumb2指令还不能支持。

使用这种方式还有一个好处,如果用户代码不操作硬件及硬件上的固定地址,那么编译好的用户程序可以在相同结构上的RT-Thread运行,例如AT91SAM7X256下的用户程序可以二进制兼容在LPC2148上运行。

动态模块加载是RT-Thread中一个非常重要的特性,发布的点大约在0.3.0 - 0.4.0之间。

出0入0汤圆

 楼主| 发表于 2009-6-16 14:42:39 | 显示全部楼层
如果能做到9楼所说的,那没什么疑问了。
elf文件执行位置与位置无关。
这么来说还是要一个类似shell的东西,告诉内核需要运行哪个elf
然后内核里面还得有这个解析elf的东西,
然后分配相应的堆栈和优先级以及其他资源,这个问题好像不是很大,可以通过文件名或者编译在文件内部某个固定地址处。
运行完毕执行某个命令回收这些资源就行了。
听起来很不错

出0入0汤圆

发表于 2009-6-16 15:23:01 | 显示全部楼层
shaolin是RT-Thread中一位非常重要的开发成员,所以确实如shaolin所说。shell可有可无,采用图形界面方式也能够“执行应用程序”;采用web方式也能够指定cgi-bin的位置。

出0入0汤圆

 楼主| 发表于 2009-6-16 17:36:17 | 显示全部楼层
web方式还不如弄过远程的ssh或者telnet
再来一个小的shell,这不就是一个精简版的实时系统么

出0入0汤圆

发表于 2009-6-21 20:14:05 | 显示全部楼层
对象处理的方法和Keil的RTX很相似,
当初看到RTX中将TCB类型转换后传入统一的链表处理函数中时,很是欣赏,
原来 RT-Thread 早就有了,看来自己是落伍了

出0入0汤圆

发表于 2009-6-21 20:18:38 | 显示全部楼层
ssh还是算了 SSL太恐怖了 那个FINSH应该可以取代telnet吧??
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-20 15:23

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表