上篇文章xenomai內核解析--同步互斥機制(一)--優先級倒置講到,對於全部內核對象:html
xnregistry
:保存內核對象,提供內核對象存儲和快速檢索。node
xnsynch
:資源抽象,提供線程與資源的同步互斥管理機制。linux
舉個應用例子,有兩個xenoami任務,使用semaphore作互斥,任務1建立一個名爲/test-sem
的semaphore,任務2打開這個semaphore,以這個過程爲例,帶你瞭解xnregistry。dom
/*任務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); .....
本片文章解析xenomai內核中的xnregistry。至於xenomai semaphore具體的內核機制及建立流程,之後文章介紹,敬請關注。post
xnregistry用於保存xenomai全局內核對象。這些對象分爲兩種,一種有name,經常使用於兩個及以上進程間,能夠經過name來找到同一對象。另外一種沒有name,經常使用於同一進程空間。線程
涉及經過字符串name來查找的內核對象稱爲命名內核對象,xenomai內核中名內核對象有:有名信號量(sem)、有名消息隊列(mq)、進程間經過label相互通信的xddp/bufp/iddp等。code
建立命名對象的時候,orm
register_obj_solts
中分配一個xnobject;key
,具體對象(cobalt_sem)的地址做爲value
保存到xnobject的成員objaddr
中。s
,選擇合適的hash bucket,該bucket在xenomai中爲object_index[]
,而後將xnobject插入選定的object_index[s]鏈表中。object_index[]
中快速獲得該內核對象。name只在建立和經過name查找時使用,一個對象經過name查找或建立後會保存一個xnhandlet,後續操做使用xnhandlet代替,提升xnobjet的訪問速度。htm
建立時註冊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有相應的機制,請關注後續文章,呵呵~~。
上面說完了命名內核對象,下面來看未命名內核對象,即非跨進程共享的。
對於沒有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註冊流程以下。
圖中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", ®istry_vfroot, &cobalt_vfroot); ret = xnvfile_init_regular("usage", &usage_vfile, ®istry_vfroot); proc_apc = xnapc_alloc("registry_export", ®istry_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(®istry_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(®ister_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_sem
、cobalt_mutex
等。
*key
對象的name或label,用戶程序可以使用name來操做內核對象,具備name的內核對象會保存到一個hash表中,方便經過name查找。若是key爲NULL,則不用。
vfilp
、vfile_u
、pnode
註冊到linux虛擬文件系統經常使用變量。
hlink
用於加入hash鏈表。
link
該對象若是未使用則用於加入空閒鏈表free_object_list,不然用於加入已使用鏈表busy_object_list。
registry
目錄,以及文件usage
,註冊後可經過/proc/xenomai/registry/usage
查看xnobject的使用狀況。$ cat /proc/xenomai/registry/usage 7/512
register_synch
,register_synch
xnregistry
:保存內核對象,提供內核對象存儲和快速檢索。
xnsynch
:資源抽象,提供線程與資源的同步互斥管理機制。
xnsynch
、xnregistry
是xenomai內核機制很是重要的組件,明白他們xenomai的資源管理機制就明白大半了。