1 名字
UTCB:Userspace Thread Control Block
2 库
#include <l4lib/arch/utcb.h>
3 描述
UTCB是一个被指定为每一个线程为IPC(Inter-Process Communication,进程间通信)消息寄存器以及私有数据本地存储的数据结构,在系统里,UTCB在线程里的地址空间是一个唯一有效的虚拟地址域,在运行期通过读取KIP的utcb域获得。
UTCB存储线程之间通过IPC传送的消息寄存器,依赖于IPC是发送还是接收,消息寄存器域要么被传送给其他进程,要么就是被其他进程消息寄存器写。详细的IPC行为请参考l4_ipc系统调用参考页。
UTCB或许还可以被用做地址空间私有的线程本地信息,比如,在当前IPC完成之前一个新的IPC被初始化的IPC堆上,saved_tag和saved_sender域目的是存储没有结束的IPC信息,每个域的详细的描述请参考下面:
struct utcb {
u32 mr[MR_TOTAL]; /* MRs that are mapped to real registers */
u32 saved_tag; /* Saved tag field for stacked ipc */
u32 saved_sender; /* Saved sender field for stacked ipc */
u32 mr_rest[MR_REST]; /* Complete the utcb to 64 words */
};
mr[MR_TOTAL]:基本信息寄存器,在ARM体系里有六个这样的寄存器,MR0~MR5作为一个最优选择,这些寄存器或许被内核通过IPC映射成真实的寄存器,但是这个行为却不被内核API保证;
Saved_tag:在IPC堆上保存IPC tag域;
Saved_sender:在IPC堆上保存sender id;
Mr_rest[MR_REST]:这些寄存器只有在full ipc的时候在一个IPC上传送,细节请查看l4_ipc;
4 UTCB分配
UTCB地址和内存的分配不是微内核维护,UTCB的分配和维护期望在用户空间处理。
UTCB地址管理有两个可能的场景:一个包含有分离地址空间多线程的pager需要执行UTCB管理功能去管理位于多地址空间里的UTCB。这意味着pager分配UTCB的时候需要在地址空间之间进行区分。比如,一个UTCB的域尺寸小于一个page的尺寸颗粒度,相同地址空间里同类的线程可以合法的在同一个page里指定UTCB,但不同地址空间的线程需要他们的UTCB位于分离的pages里去保护。
另一个场景是pager是一个所有的子线程都位于pager地址空间的多线程simpler。这种情况,一旦所有的UTCB位于共享地址空间,pager或许只是使用一个内存和虚拟地址池去管理每一个UTCB域。
注意:在libl4里有些库功能来管理以上这两种场景。
UTCB可以包含任何的虚拟地址,然而这里有一个utcb区域必须位于一个不相交的虚拟内存域里的限制。这是需要的,是因为当IPC被建立,内核在UTCB域之间进行直接拷贝,没有页表的操作,换句话说,将要通过IPC通信的两个线程必须有在不同虚拟地址域里的UTCB一边内核做直接拷贝。
创建一个UTCB最简单的解决办法是静态的通过下面的宏声明一个UTCB对齐尺寸的utcb结构:
#define DECLARE_UTCB(name) struct utcb name ALIGN(sizeof(struct utcb))
使用:
DECLARE_UTCB(utcb);
一旦使用这种最简单的解决方案,通常在没有特别强调不相交的天然的程序地址空间里分配一个utcb,通过上面的描述,内核需要分配位于和系统里其他UTCB地址不相交的虚拟地址空间域里的结构,或者至少拥有UTCB可能存在两方IPC调用的线程要不相交。在声明时上面的声明可能被一个使用指定段属性的特定段取代。
Pagers可以通过l4_exchange_registers()设置线程的utcb地址,详细说明参考l4_exchange_registers。
UTCB结构可以是一个可变长度的和可以通过配置或者不同的体系改变其长度,在ARM体系,它被设置成256字节,UTCB结构可以改变其目的,新的域在UTCB上被保留。
5 L4 USERSPACE LIBRARY
static inline unsigned int read_mr(int offset);
static inline void write_mr(unsigned int offset, unsigned int val)