RT-Thread 内核实验 1 任务的基本管理

 RT-Thread 内核实验 1  任务的基本管理
实验目的: 
—    理解 RTOS 中任务管理的基本原理,了解任务的基本状态及其变迁过程;
—    掌握 RT-Thread 任务管理子系统中的任务创建,启动,延时机制
—    掌握 RT-Thread 任务管理子系统中静态任务与动态任务创建的区别
 
实验设计: 
为了体现任务的状态切换过程,本实验设计了两个线程,分别是 thread1,thread2,此外,系统
中还有另外一个空闲任务,当没有其他任务运行时,系统自动调度空闲任务并投入运行。 
 
 
 
实验流程: 
1)   系统进入应用程序入口
2)   初始化静态线程  thread1 ,线程的入口是  thread1_entry, 参数是  RT_NULL,线程栈是
thread1_stack,优先级是 30,时间片是 10 个 OS Tick
3)   启动线程 thread1
4)   创建动态线程 thread2,线程的入口是 thread2_entry,,参数是 RT_NULL,栈空间是 512,优
先级是 31,时间片是 25 个 OS Tick
5)   启动线程 thread2
6)   [1]系统首先调度 thread1 投入运行,打印第 0 次运行的信息,然后通过延时函数将自己挂起
100 个 OS Tick,系统转入调度 thread2 投入运行
7)   [2]Thread2 打印第 0 次运行信息,然后通过延时函数将自己挂起 50 个 OS Tick
8)   [3]系统中无任务运行,转入调度空闲任务
9)   [4]50 个 OS Tick 时间后,Thread2 被唤醒,打印第 1 次运行的信息,继续通过延时函数将自
己挂起 50 个 OS Tick
10) [5]系统中无任务运行,系统转入调度空闲任务,运行 50 个 OS Tick 11) [6]Thread1 被唤醒,打印第 1 次运行信息,继续挂起 100 个 OS Tick
12) [7]Thread2 被唤醒,打印第 2 次运行的信息,继续挂起 50 个 OS Tick
13) [8]系统中无任务运行,系统转入调度空闲任务,运行 50 个 OS Tick
14) [9]Thread2 被唤醒,打印第 3 次运行的信息,继续挂起 50 个 OS Tick
15) [10]系统中无任务运行,系统转入调度空闲任务,运行 50 个 OS Tick
16) 循环上述过程
 
源程序说明: 
 
     /*  线程 1 的对象和运行时用到的栈  */
static struct rt_thread thread1;
ALIGN(4)
    static rt_uint8_t thread1_stack[512];
 
    /*  线程 1 入口  */
    void thread1_entry(void* parameter)
    {
        int i;
 
        while (1)
        {
            for (i = 0; i < 10; i ++)
            {
                rt_kprintf("%d\n", i);
 
                /*  延时 100 个 OS Tick */
                rt_thread_delay(100);
            }
        }
    }
 
    /*  线程 2 入口  */
    void thread2_entry(void* parameter)
    {
        int count = 0;
        while (1)
        {
            rt_kprintf("Thread2 count:%d\n", ++count);
 
            /*  延时 50 个 OS Tick */
            rt_thread_delay(50);
        }
    }
 
    /*  用户应用程序入口  */
    int rt_application_init()
    {
        rt_thread_t thread2_ptr;
        rt_err_t result;
         /*  初始化线程 1 */
        /*  线程的入口是 thread1_entry ,参数是 RT_NULL
       *  线程栈是 thread1_stack
         *  优先级是 200 ,时间片是 10 个 OS Tick
         */
        result = rt_thread_init(&thread1,
            "thread1",
            thread1_entry, RT_NULL,
            &thread1_stack[0], sizeof(thread1_stack),
            30, 10);
 
        /*  启动线程  */
        if (result == RT_EOK) rt_thread_startup(&thread1);
 
        /*  创建线程 2 */
        /*  线程的入口是 thread2_entry,  参数是 RT_NULL
         *  栈空间是 512 ,优先级是 250 ,时间片是 25 个 OS Tick
         */
        thread2_ptr = rt_thread_create("thread2",
            thread2_entry, RT_NULL,
            512, 31, 25);
 
        /*  启动线程  */
        if (thread2_ptr != RT_NULL) rt_thread_startup(thread2_ptr);
 
        return 0;
    }
 
输出信息: 
运行程序,通过观察串口输出,就可以观察到任务的运行和切换情况了。 
 
断点设置 
使用 MDK 调试工具在程序中设置一些合理断点来运行,可以清晰地看到线程运行和切换的完
整过程。 
 
TIPS: 动态线程和静态线程 
RT-Thread 中支持静态和动态两种定义方式。用线程来举例的话,rt_thread_init 对应静态定义方
式,rt_thread_create 对应动态定义方式。  
使用静态定义方式时,必须先定义静态的线程控制块,并且定义好堆栈空间,然后调用
rt_thread_init  来完成线程的初始化工作。采用这种方式,线程控制块和堆栈占用的内存会放在
RW  段,这段空间在编译时就已经确定,它不是可以动态分配的,所以不能被释放,而只能使
用 rt_thread_detach 函数将该线程控制块从对象管理器中脱离。
使用动态定义方式 rt_thread_create 时,RT-Thread 会动态申请线程控制块和堆栈空间。在编译时,
编译器是不会感知到这段空间的,只有在程序运行时,RT-Thread 才会从系统堆中申请分配这段
内存空间,当不需要使用该线程时,调用 rt_thread_delete 函数就会将这段申请的内存空间重新
释放到内存堆中。
这两种方式各有利弊,静态定义方式会占用 RW/ZI 空间,但是不需要动态分配内存,运行时效
率较高,实时性较好。  动态方式不会占用额外的 RW/ZI  空间,占用空间小,但是运行时需要
动态分配内存,效率没有静态方式高。  
总的来说,这两种方式就是空间和时间效率的平衡,可以根据实际环境需求选择采用具体的分
配方式。
 

你可能感兴趣的:(thread,OS,null,application,任务,delay)