对象核心

对象核心是一种内核调试工具,可用于标识已注册的对象并对其执行操作。

对象核心概念

每个对象实例都嵌入一个名为 obj_core 的对象核心字段。同一类型的对象通过各自的对象核心连接为单向链表。每个对象核心还链接到其所属的对象类型。每个对象类型包含一条单向链表,将该类型的所有对象核心连接起来。对象类型之间也通过单向链表连接。这些链接使调试工具能够遍历系统中的所有对象。

对象核心已集成到以下内核对象中:

开发者也可以按需将对象核心集成到项目中的其他对象中。

对象核心统计概念

多种内核对象支持收集和报告统计信息。对象核心通过对象核心统计机制,提供统一的信息获取方式。启用此功能后,对象类型包含一个指向统计描述符的指针,该描述符定义了已启用的、用于访问对象统计信息的各种操作。此外,对象核心还包含一个指向该对象“原始”统计信息的指针。原始数据是与统计信息相关的、未经处理的数据。查询数据可能是“原始”数据,也可能经过某种计算处理,例如求平均值。

下表列出了已集成对象核心统计功能的对象,以及各自用于“原始”数据和“查询”数据的结构体。

对象

原始数据类型

查询数据类型

struct mem_slab

struct mem_slab_info

struct sys_memory_stats

struct sys_mem_blocks

struct sys_mem_blocks_info

struct sys_memory_stats

struct k_thread

struct k_cycle_stats

struct k_thread_runtime_stats

struct _cpu

struct k_cycle_stats

struct k_thread_runtime_stats

struct z_kernel

struct k_cycle_stats[num CPUs]

struct k_thread_runtime_stats

实现

定义新的对象类型

使用 k_obj_type 类型的全局变量定义对象类型。必须在初始化该类型的任何对象之前初始化对象类型。以下代码展示如何初始化新的对象类型,使其可用于对象核心和对象核心统计。

/* Unique object type ID */

#define K_OBJ_TYPE_MY_NEW_TYPE  K_OBJ_TYPE_ID_GEN("UNIQ")
struct k_obj_type  my_obj_type;

struct my_obj_type_raw_info {
    ...
};

struct my_obj_type_query_stats {
    ...
};

struct my_new_obj {
    ...
    struct k_obj_core obj_core;
    struct my_obj_type_raw_info  info;
};

struct k_obj_core_stats_desc my_obj_type_stats_desc = {
    .raw_size = sizeof(struct my_obj_type_raw_stats),
    .query_size = sizeof(struct my_obj_type_query_stats),
    .raw = my_obj_type_stats_raw,
    .query = my_obj_type_stats_query,
    .reset = my_obj_type_stats_reset,
    .disable = NULL,    /* Stats gathering is always on */
    .enable = NULL,     /* Stats gathering is always on */
};

void my_obj_type_init(void)
{
    z_obj_type_init(&my_obj_type, K_OBJ_TYPE_MY_NEW_TYPE,
                    offsetof(struct my_new_obj, obj_core);
    k_obj_type_stats_init(&my_obj_type, &my_obj_type_stats_desc);
}

初始化新的对象核心

对于已集成对象核心框架的内核对象,其对象核心会在对象初始化时自动初始化。但是,要将自定义对象加入框架,开发者需要初始化对象核心并将其链接起来。以下代码在上例的基础上初始化对象核心。

void my_new_obj_init(struct my_new_obj *new_obj)
{
    ...
    k_obj_core_init(K_OBJ_CORE(new_obj), &my_obj_type);
    k_obj_core_link(K_OBJ_CORE(new_obj));
    k_obj_core_stats_register(K_OBJ_CORE(new_obj), &new_obj->raw_stats,
                              sizeof(struct my_obj_type_raw_info));
}

遍历对象核心列表

有两个函数可用于遍历链接到某个对象类型的对象核心列表:k_obj_type_walk_locked() 和 k_obj_type_walk_unlocked()。以下代码在上例的基础上,打印该新对象类型的所有对象的地址。

int walk_op(struct k_obj_core *obj_core, void *data)
{
    uint8_t *ptr;

    ptr = obj_core;
    ptr -= obj_core->type->obj_core_offset;

    printk("%p\n", ptr);

    return 0;
}

void print_object_addresses(void)
{
    struct k_obj_type *obj_type;

    /* Find the object type */

    obj_type = k_obj_type_find(K_OBJ_TYPE_MY_NEW_TYPE);

    /* Walk the list of objects */

    k_obj_type_walk_unlocked(obj_type, walk_op, NULL);
}

查询对象核心统计信息

以下代码在前述示例的基础上,展示已集成对象核心统计框架的对象如何获取查询数据,以及如何重置对象的统计信息。

struct my_new_obj my_obj;

...

void my_func(void)
{
    struct my_obj_type_query_stats  my_stats;
    int  status;

    my_obj_type_init(&my_obj);

    ...

    status = k_obj_core_stats_query(K_OBJ_CORE(&my_obj),
                                    &my_stats, sizeof(my_stats));
    if (status != 0) {
        /* Failed to get stats */
        ...
    } else {
        k_obj_core_stats_reset(K_OBJ_CORE(&my_obj));
    }

    ...
}

配置选项

相关配置选项:

API 参考

Object Core APIs
Object Core Statistics APIs