RT-Thread 入门学习笔记 - 查看线程栈的地址

RT-Thread 入门学习笔记 - menuconfig Kconfig的使用

RT-Thread 入门学习笔记 - 熟悉动态内存申请与释放

RT-Thread 入门学习笔记 - 查看线程栈的地址

RT-Thread 入门学习笔记 - 解决RT_ASSERT失效的问题

前言

  • 最近在看线程部分,发现,list_thread 不能查看各个线程的栈地址
  • 熟悉了内核对象的操作,了解了RT-Thread 线程的结构体,可以写个测试代码查看线程栈地址

 

RT-Thread线程结构体

  • RT-Thread 线程结构体相对较为复杂,包含较多的成员。
  • 具体可以查看:<rtdef.h>中的:struct rt_thread 结构体
  • 线程栈地址,就是rt_thread中的:
    /* stack point and entry */
    void       *sp;                                     /**< stack point */
    void       *entry;                                  /**< entry */
    void       *parameter;                              /**< parameter */
    void       *stack_addr;                             /**< stack address */
    rt_uint32_t stack_size;                             /**< stack size */

 

仿照list_thread编写测试代码

void dump_thread_ex(void)
{
    rt_uint8_t index = 0;
    rt_uint8_t obj_size = 0;
    int thread_cnt = rt_object_get_length(RT_Object_Class_Thread);

    rt_kprintf("%s: thread count = %d\n", __func__, thread_cnt);

    char *thread_buf = rt_malloc(thread_cnt * 4);

    if (thread_buf == RT_NULL)
    {
        rt_kprintf("%s: malloc failed!\n", __func__);
        return;
    }

    rt_object_t* obj_pointers = (rt_object_t *)thread_buf;

    obj_size = rt_object_get_pointers(RT_Object_Class_Thread, obj_pointers, thread_cnt);
    rt_kprintf("object init : object size=%d\n", obj_size);

    rt_kprintf("|    name    | pri | status | stack addr | stack size | used | remain tick | err |\n");
    rt_kprintf("+------------+-----+--------+------------+------------+------+-------------+-----+\n");
    for (index = 0; index < obj_size; index++)
    {
        rt_thread_t ptr_t = (rt_thread_t)obj_pointers[index];
        if (obj_pointers[index] == RT_NULL)
        {
            break;
        }

        rt_uint8_t *ptr = (rt_uint8_t *)ptr_t->stack_addr;
        while (*ptr == '#')
            ptr ++;
        rt_uint8_t stack_used_percent = (ptr_t->stack_size - ((rt_ubase_t) ptr - (rt_ubase_t) ptr_t->stack_addr))
            * 100/ ptr_t->stack_size;

        rt_kprintf("| %10s | %3d ", obj_pointers[index]->name, ptr_t->current_priority);

        rt_uint8_t stat = (ptr_t->stat & RT_THREAD_STAT_MASK);
        if (stat == RT_THREAD_READY)
            rt_kprintf("| ready  ");
        else if (stat == RT_THREAD_SUSPEND)
            rt_kprintf("| suspend");
        else if (stat == RT_THREAD_INIT)
            rt_kprintf("| init   ");
        else if (stat == RT_THREAD_CLOSE)
            rt_kprintf("| close  ");
        else if (stat == RT_THREAD_RUNNING)
            rt_kprintf("| running");

        rt_kprintf("| 0x%08x | 0x%08x | %02d%%  | 0x%08x  | %03d |\n", ptr_t->stack_addr,
            ptr_t->stack_size, stack_used_percent, ptr_t->remaining_tick, ptr_t->error);
    }
    rt_kprintf("+------------+-----+--------+------------+------------+------+-------------+-----+\n");
    rt_free(thread_buf);
}

MSH_CMD_EXPORT(dump_thread_ex, list thread ex);

 

运行效果

msh />dump_thread_ex
dump_thread_ex: thread count = 5
object init : object size=5
|    name    | pri | flag | type | stack addr | stack size | used | remain tick |
+------------+-----+------+------+------------+------------+------+-------------+
|     tshell |  20 |    0 | 0x01 | 0x20008a70 | 0x00001000 | 07%  | 0x00000008  |
|       usbd |   8 |    0 | 0x81 | 0x20002714 | 0x00001000 | 04%  | 0x00000014  |
| ulog_async |  30 |    0 | 0x01 | 0x20005e98 | 0x00001000 | 34%  | 0x00000009  |
|   alarmsvc |  10 |    0 | 0x01 | 0x20004c80 | 0x00000800 | 07%  | 0x00000005  |
|     tidle0 |  31 |    0 | 0x81 | 0x20001c24 | 0x00000800 | 06%  | 0x00000006  |
+------------+-----+------+------+------------+------------+------+-------------+
msh />list_th 
list_thread
msh />list_thread
thread           pri  status      sp     stack size max used left tick  error
---------------- ---  ------- ---------- ----------  ------  ---------- ---
tshell            20  running 0x0000013c 0x00001000    12%   0x00000009 000
usbd               8  suspend 0x000000a8 0x00001000    04%   0x00000014 000
ulog_async        30  suspend 0x0000007c 0x00001000    34%   0x0000000b 000
alarmsvc          10  suspend 0x0000009c 0x00000800    07%   0x00000005 000
tidle0            31  ready   0x00000078 0x00000800    06%   0x00000012 000
msh />
  • 了解线程栈,明白线程栈地址的分配,可以用于调试排查内存溢出等错误。

 

总结

  • 需要继续研究RT-Thread 线程的结构与操作方法
  • 通过内核对象,了解线程栈的查看方法
  • 熟悉RT-Thread 内核对象的查看方法,如list_device

猜你喜欢

转载自blog.csdn.net/tcjy1000/article/details/113854463