1. 概述

上篇文章xenomai内核解析--同步互斥机制(一)--优先级倒置讲到,对于所有内核对象:

xnregistry:保存内核对象,提供内核对象存储和快速检索。

xnsynch:资源抽象,提供线程与资源的同步互斥管理机制。

举个应用例子,有两个xenoami任务,使用semaphore做互斥,任务1创建一个名为/test-sem的semaphore,任务2打开这个semaphore,以这个过程为例,带你了解xnregistry。

/*任务1*/
sem_t *dome_sem;
.....
dome_sem = sem_open("/test-sem", O_CREAT | O_EXCL, 0666, 0);
if (dome_sem == SEM_FAILED)
error(1, errno, "sem_open()");
.....
sem_wait(dome_sem);
.....
sem_post(dome_sem);
.....
/*任务2*/
sem_t *dome_sem;
.....
dome_sem = sem_open("/test-sem", 0);
if (dome_sem == SEM_FAILED)
error(1, errno, "sem_open()");
.....
sem_wait(dome_sem);
.....
sem_post(dome_sem);
.....
  • 问题1:任务1创建的这个semaphore是如何管理的?
  • 问题2:任务2又是如何通过name找到它的?

本片文章解析xenomai内核中的xnregistry。至于xenomai semaphore具体的内核机制及创建流程,以后文章介绍,敬请关注。

2. 命名内核对象管理

xnregistry用于保存xenomai全局内核对象。这些对象分为两种,一种有name,常用于两个及以上进程间,可以通过name来找到同一对象。另一种没有name,常用于同一进程空间。

涉及通过字符串name来查找的内核对象称为命名内核对象,xenomai内核中名内核对象有:有名信号量(sem)、有名消息队列(mq)、进程间通过label相互通讯的xddp/bufp/iddp等。

创建命名对象的时候,

  1. 先从register_obj_solts中分配一个xnobject;
  2. 然后将name作为xnobject成员key具体对象(cobalt_sem)的地址作为value保存到xnobject的成员objaddr中。
  3. 向xnregistry中存储该xnobject时,会将name作为key经过hash运算,根据运算得到的hash值s,选择合适的hash bucket,该bucket在xenomai中为object_index[],然后将xnobject插入选定的object_index[s]链表中。
  4. 当另一个线程open同一name的对象时,通过name可从object_index[]中快速得到该内核对象。

name只在创建和通过name查找时使用,一个对象通过name查找或创建后会保存一个xnhandlet,后续操作使用xnhandlet代替,提高xnobjet的访问速度。

创建时注册cobalt_sem流程如下所示。

  • register_obj_solts用于保存型号量这个xnobject,上面的问题1.
  • object_index用于检索,上面的问题2。

我们接着来看创建后保存的这个xnhandlet,cobalt_sem创建完成后会保存xnhandlet到信号量句柄sem_t中,并拷贝到用户空间,我们可以来看一下libcobalt中的句柄sem_t的形式:

struct cobalt_sem_shadow {
__u32 magic;
__s32 state_offset;
xnhandle_t handle;
} shadow_sem;

从上面图中我们可以看到xnhandlet是一个偏移量,表示这个xnobject基于register_obj_solts的地址偏移,为什么要直接保存到句柄sem_t中呢?sem_wait()/sem_post()操作进入内核的时候就可以直接去获取xnobject做相应的操作了。

另外想一下,一个运行在用户态的实时应用,每次PV操作的时候都需要执行系统调用,对实时系统来说不太友好,毕竟系统调用也是需要花费时间的,xnhandlet只能解决内核里定位xnobject的速度问题,我们能不能不要每次都执行系统调用呢?答案是肯定的,xenomai有相应的机制,请关注后续文章,呵呵~~。

3. 未命名内核对象管理

上面说完了命名内核对象,下面来看未命名内核对象,即非跨进程共享的。

对于没有name的内核对象,通过xnregistry提供的匿名接口来保存。所谓的匿名保存,key为NULL,具体对象(cobalt_sem)的地址作为value到一个分配的结构体xnobject后,不经hash运算,直接计算xnobject基于某个固定地址的偏移量xnhandle_t,通常xnhandle_t会在用户空间的对象结构体中保存一份,比如sem_t、pthread_mutex_t等;之后用户空间对该对象发起系统调用时就可以通过xnhandle_t快速从xnregistry获取该对象,使用匿名的内核对象有:进程间的互斥量mutex、未命名信号量sem、条件变量condition variable、事件event、monitor。

同样以未命名信号量为例,内核对象cobalt_sem注册流程如下。

4. xnregistry初始化流程

图中resitry_obj_slots[]其大小内核构建时CONFIG_XENO_OPT_REGISTRY_NRSLOTS指定,默认大小512,具体内存在xenomai初始化时调用xnregistry_init()初始化xnregistry时分配。

static int __init xenomai_init(void)
->sys_init()
->xnregistry_init()

xnregistry_init()具体流程如下。

int xnregistry_init(void)
{
int n, ret __maybe_unused; registry_obj_slots = kmalloc(CONFIG_XENO_OPT_REGISTRY_NRSLOTS *
sizeof(struct xnobject), GFP_KERNEL);
.....
#ifdef CONFIG_XENO_OPT_VFILE
ret = xnvfile_init_dir("registry", &registry_vfroot, &cobalt_vfroot);
ret = xnvfile_init_regular("usage", &usage_vfile, &registry_vfroot);
proc_apc = xnapc_alloc("registry_export", &registry_proc_schedule, NULL);
#endif /* CONFIG_XENO_OPT_VFILE */
next_object_stamp = 0; for (n = 0; n < CONFIG_XENO_OPT_REGISTRY_NRSLOTS; n++) {
registry_obj_slots[n].objaddr = NULL;
list_add_tail(&registry_obj_slots[n].link,
&free_object_list);
}
/* Slot #0 is reserved/invalid. */
list_get_entry(&free_object_list, struct xnobject, link);
nr_active_objects = 1; nr_object_entries = xnregistry_hash_size();
object_index = kmalloc(sizeof(*object_index) *
nr_object_entries, GFP_KERNEL); for (n = 0; n < nr_object_entries; n++)
INIT_HLIST_HEAD(&object_index[n]); xnsynch_init(&register_synch, XNSYNCH_FIFO, NULL);
return 0;
}

1.先分配CONFIG_XENO_OPT_REGISTRY_NRSLOTS个xnobject的空间,xenomai运行过程中的xnobject从registry_obj_slots中直接获取,这样就避免频繁的内存申请影响实时性。struct xnobject结构如下:

struct xnobject {
void *objaddr;
const char *key; /* !< Hash key. May be NULL if anonynous. */
unsigned long cstamp; /* !< Creation stamp. */
#ifdef CONFIG_XENO_OPT_VFILE
struct xnpnode *pnode; /* !< v-file information class. */
union {
struct {
struct xnvfile_rev_tag tag;
struct xnvfile_snapshot file;
} vfsnap; /* !< virtual snapshot file. */
struct xnvfile_regular vfreg; /* !< virtual regular file */
struct xnvfile_link link; /* !< virtual link. */
} vfile_u;
struct xnvfile *vfilp;
#endif /* CONFIG_XENO_OPT_VFILE */
struct hlist_node hlink; /* !< Link in h-table */
struct list_head link;
};

objaddr指向具体的内核对象,如cobalt_semcobalt_mutex等。

*key 对象的name或label,用户程序可使用name来操作内核对象,具有name的内核对象会保存到一个hash表中,方便通过name查找。如果key为NULL,则不用。

vfilpvfile_upnode 注册到linux虚拟文件系统常用变量。

hlink用于加入hash链表。

link 该对象如果未使用则用于加入空闲链表free_object_list,否则用于加入已使用链表busy_object_list。

  1. 在linux虚拟文件系统proc目录下创建registry目录,以及文件usage,注册后可通过/proc/xenomai/registry/usage查看xnobject的使用情况。
$ cat /proc/xenomai/registry/usage
7/512
  1. 将刚分配的空闲xnobject插入free_object_list链表。
  2. 将free_object_list的第一个xnobject节点保留,记录xnobject已使用数nr_active_objects。
  3. 分配散列表object_index[]的空间,并初始化。
  4. 初始化registry资源同步对象register_synch,register_synch

5. xnregistry总结

xnregistry:保存内核对象,提供内核对象存储和快速检索。

xnsynch:资源抽象,提供线程与资源的同步互斥管理机制。

xnsynchxnregistry是xenomai内核机制非常重要的组件,明白他们xenomai的资源管理机制就明白大半了。

xenomai内核解析---内核对象注册表—xnregistry(重要组件)的更多相关文章

  1. 【原创】xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(二)--实时与非实时关联(bind流程)

    版权声明:本文为本文为博主原创文章,转载请注明出处.如有问题,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 1.概述 上篇文章介绍了实时端socket创建和配置 ...

  2. 【原创】xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(一)--实时端socket创建流程

    版权声明:本文为本文为博主原创文章,转载请注明出处.如有问题,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 1.概述 上篇文章xenomai内核解析--实时IP ...

  3. 《天书夜读:从汇编语言到windows内核编程》八 文件操作与注册表操作

    1)Windows运用程序的文件与注册表操作进入R0层之后,都有对应的内核函数实现.在windows内核中,无论打开的是文件.注册表或者设备,都需要使用InitializeObjectAttribut ...

  4. xenomai内核解析之信号signal(二)---xenomai信号处理机制

    xenomai信号 上篇文章讲了linux的信号在内核的发送与处理流程,现在加入了cobalt核,Cobalt内核为xenomai线程提供了信号机制.下面一一解析xenomai内核的信号处理机制. 1 ...

  5. 【原创】xenomai内核解析--同步互斥机制(一)--优先级倒置

    版权声明:本文为本文为博主原创文章,转载请注明出处.如有错误,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 目录 一.xenomai 资源管理简要 二.优先级倒 ...

  6. 【xenomai内核解析】系列文章大纲

    xenomai内核解析 本博客为本人学习linux实时操作系统框架xenomai的一些记录,主要剖析xenomai内核实现,以及与linux相关的知识.方便读者定位具体文章,现列出本博客大纲,后续会陆 ...

  7. 驱动开发:内核枚举Registry注册表回调

    在笔者上一篇文章<驱动开发:内核枚举LoadImage映像回调>中LyShark教大家实现了枚举系统回调中的LoadImage通知消息,本章将实现对Registry注册表通知消息的枚举,与 ...

  8. Windows进程的内核对象句柄表

    当一个进程被初始化时,系统要为它分配一个句柄表.该句柄表只用于内核对象 ,不用于用户对象或GDI对象. 创建内核对象 当进程初次被初始化时,它的句柄表是空的.然后,当进程中的线程调用创建内核对象的函数 ...

  9. 【原创】xenomai内核解析--双核系统调用(二)--应用如何区分xenomai/linux系统调用或服务

    版权声明:本文为本文为博主原创文章,转载请注明出处.如有错误,欢迎指正. 1. 引出问题 上一篇文章xenomai内核解析--双核系统调用(一)以X86处理器为例,分析了xenomai内核调用的流程, ...

随机推荐

  1. 黎活明8天快速掌握android视频教程--18_在SQLite中使用事务

    1 所谓的事业就是一系列的操作 比如:执行转账操作:将personid=1的账户转账10元到personid=2的账号中 所以的一系列操作就是:personid=1的账户钱要减少10元 personi ...

  2. 僵尸扫描-scapy、nmap

    如果不知道僵尸扫描是什么,请参考我的这篇博客 实验环境: kali(攻击者) 192.168.0.103 metasploitable2(目标主机) 192.168.0.104 win xp sp2( ...

  3. MFC线程(二):线程同步临界区CRITICAL SECTION

    当多个线程同时使用相同的资源时,由于是并发执行,不能保证先后顺序.所以假如时一个公共变量被几个线程同时使用会造成该变量值的混乱. 下面来举个简单例子. 假如有一个字符数组变量 char g_charA ...

  4. postman无法正常启动

    想请教下各位大神,我电脑的postman打开之后就一直转,没法启动是怎么回事?重装了不同版本的也是同样的情况,重启电脑也没用...同样的安装包,在别的电脑上就能正常打开!有什么办法解决吗?  0 20 ...

  5. python冷知识

    目录 省略号也是对象 奇怪的字符串 and 和 or 的取值顺序 访问类中的私有方法 时有时无的切片异常 两次 return for 死循环 intern机制 省略号也是对象 在python中一切皆对 ...

  6. 队列的顺序存储与链式存储c语言实现

    一. 队列 1.队列定义:只允许在表的一端进行插入,表的另一端进行删除操作的线性表. 2.循环队列:把存储队列的顺序队列在逻辑上视为一个环. 循环队列状态: 初始时:Q.front=Q.rear=0 ...

  7. FreeMarkerz在List中取任意一条数据的某一个值

    首先你要知道要取的数据的下标 <#list itemsList as item> <#if item_index==1> <#if "${item.value} ...

  8. 执行dotnet *.dll启动项目,如何修改环境变量----ASPNETCORE_ENVIRONMENT

    docker环境: 启动容器时,添加参数:-e " ASPNETCORE_ENVIRONMENT=Development" windows系统: 命令行,以管理员身份运行:setx ...

  9. 基于ASP.NET core的MVC站点开发笔记 0x01

    基于ASP.NET core的MVC站点开发笔记 0x01 我的环境 OS type:mac Software:vscode Dotnet core version:2.0/3.1 dotnet sd ...

  10. CSS 3中-webkit-, -moz-, -o-, -ms-这些私有前缀的含义和兼容

    css3作为页面样式的表现语言,增加了很多新的属性,但是部分css3属性在一些浏览器上还处于试验阶段,所以为了有效的显示css3的样式,对应不同的浏览器内核需要不同的前缀声明,例如: -moz- :F ...