菜单

xnregistry:内核对象注册与管理

xnregistry:全局对象注册表

在实时系统中,任务之间的同步与通信需要依赖各种内核对象,如信号量、互斥锁、消息队列等。为了支持进程间共享和快速检索,Xenomai 提供了 xnregistry,用于统一管理和访问这些内核对象。

什么是 xnregistry?

xnregistryXenomai 内核的全局对象注册表,负责管理内核中的命名和未命名对象。它提供了一种机制,允许内核对象以唯一的标识符(如名称)注册,便于在内核和用户空间中查找和访问。

xnregistry 的作用

  • 统一管理:维护内核对象的生命周期,确保资源的正确分配和释放。
  • 快速检索:通过高效的哈希表结构,实现对象的快速查找,满足实时系统的性能要求。
  • 进程间通信:支持命名对象的共享,方便不同进程或线程之间的同步与通信。

命名内核对象的管理

命名内核对象是指在创建时指定了名称的对象,通常用于多个进程之间的共享和通信。常见的命名内核对象包括:

  • 有名信号量(sem)
  • 有名消息队列(mq)
  • 实时套接字(如 xddp、bufp、iddp)
创建和注册过程

以两个 Xenomai 任务通过信号量进行同步为例:

任务 1 创建一个名为 /tmp/sem1 的信号量

c 复制代码
/* 任务 1 */
sem_t *demo_sem;

demo_sem = sem_open("/tmp/sem1", O_CREAT | O_EXCL, 0666, 0);
if (demo_sem == SEM_FAILED)
    perror("sem_open");

sem_wait(demo_sem);
/* ... */
sem_post(demo_sem);

任务 2 打开同名信号量

c 复制代码
/* 任务 2 */
sem_t *demo_sem;

demo_sem = sem_open("/tmp/sem1", 0);
if (demo_sem == SEM_FAILED)
    perror("sem_open");

sem_wait(demo_sem);
/* ... */
sem_post(demo_sem);

当任务 1 调用 sem_open 创建信号量时,内核会进行以下操作:

  1. 分配 xnobject 结构体:从 registry_obj_slots 中获取一个空闲的 xnobject,用于表示信号量对象。
  2. 设置 xnobject 的属性:
    • key:设置为信号量的名称 /tmp/sem1
    • objaddr:指向实际的信号量对象(如 cobalt_sem)。
  3. 插入哈希表:
  • 对名称进行哈希计算,得到索引值 s。
  • xnobject 插入到 object_index[s] 哈希桶对应的链表中。

任务 2 想要打开同名信号量时,执行以下步骤:

  1. 计算名称的哈希值:对 /tmp/sem1 进行哈希计算,得到索引值 s。
  2. 在哈希表中查找:
    • 遍历 object_index[s] 链表,比较每个 xnobjectkey
    • 找到匹配的 xnobject 后,获取其 objaddr,即信号量对象的地址。

在成功创建或打开信号量后,系统会生成一个 xnhandle_t,表示对象的句柄。这个句柄通常是 xnobjectregistry_obj_slots 数组中的偏移量。任务在后续操作(如 sem_waitsem_post)中,使用这个句柄快速访问信号量对象,避免再次通过名称查找。

未命名内核对象的管理

未命名内核对象通常用于单个进程或线程内部,不需要跨进程共享。例如:

  • 未命名信号量(sem)
  • 互斥锁(mutex)
  • 条件变量(condition variable)
  • 事件(event)

管理机制

未命名对象在创建时:

  1. 分配 xnobject:同样从 registry_obj_slots 中获取一个 xnobject
  2. 设置属性:
  • key:设置为 NULL,表示匿名对象。
  • objaddr:指向具体的内核对象。
  1. 不插入哈希表:由于没有名称,匿名对象不需要插入到哈希表中。
  2. 生成句柄:返回 xnhandle_t,供后续操作使用。

访问方式

任务在后续对未命名对象的操作中,使用句柄 xnhandle_t 直接访问对象,而不需要通过名称查找。这种方式提高了访问速度,满足实时系统对性能的要求。

xnregistry 的初始化流程

初始化步骤

在系统启动时会初始化 xnregistry,具体步骤包括:

  1. 分配对象槽(registry_obj_slots):
    • 分配固定数量的 xnobject,默认值为 4096。
  2. 初始化空闲链表(free_object_list):
    • 将所有分配的 xnobject 加入到空闲链表中,供后续分配使用。
  3. 创建哈希表(object_index):
    • 根据需要的哈希表大小,分配 object_index 数组,并初始化每个哈希桶。
  4. 初始化同步机制(register_synch):
    • 创建同步对象,确保对 xnregistry 的并发访问是线程安全的。
最近修改: 2025-07-24