seL4-权能 capability
在配置好环境并且可以运行 hello world 后,开始学习seL4 的权能 capabilities。与hello world类似,先做好基础的工作(本来想直接学习中断的,发现还不行,和haskell-stack相关的有个地方可能网络有问题,ninja报错,不理解。还是先一步一步跟着 tutorials 学)。
./init --tut capabilities
# building the tutorial exercise
cd capabilities_build
ninja
权能这部分需要学习 CNode, CSpace, CSlot,学会如何触发一个权能capability,如何删除和拷贝CSlots。
权能这部分的学习我还参考了PPT 基于seL4的分区操作系统
设计。
capability
访问内核资源的钥匙🔑,包含(资源地址,权限)。
权能控制访问的对象可以说内核对象(例如TCB)、抽象资源(IRQ Control),和 untyped 权能(内存管理、分配)。
一个进程要访问一个内核对象,必须拥有这个对象相应的权能。
一个权能节点 CNode 是存储权能的数组,即CSlot。CNode位于内核空间中。一个进程可以有很多CNode,这些Cnode共同组成权能空间Cspace(即这个进程的所有权能)。
CSlot 用结构体 cte_t
表示。
/* Capability table entry (CTE) */
struct cte {
cap_t cap;
mdb_node_t cteMDBNode;
};
typedef struct cte cte_t;
cap_t
表示权限。
struct cap {
uint64_t words[2];
};
typedef struct cap cap_t;
mdb_node
表示资源地址。
struct mdb_node {
uint64_t words[2];
};
typedef struct mdb_node mdb_node_t;
root task
seL4内核只创建一个进程(root task,根任务)。其它进程或线程由根任务创建。
seL4_CapInitThreadTCB
就是在 root task 的 CNode 里的 CSlot,包含 root task TCB 的权能。
bootinfo 存放了 root task 初始化的信息。
CNodes 和 CSlots
一个权能节点 CNode 相当于存储权能的数组。一个权能节点包含很多 CSlot。在例子中,seL4_CapInitThreadTCB
就是在 root task 的 CNode 里的 CSlot,包含 root task TCB 的权能。CNode 里的 CSlot 都可以分为以下几个状态:
- empty: CNode slot 是一个空的权能。
- full: 这个 slot 包含一个对内核资源的权能。
第0个 CSlot 约定为 empty,避免使用到未初始化的 slot。
info->CNodeSizeBits
给出初始 CNode 的大小,即包含 1 << CNodeSizeBits
个 CSlots。一个 CSlot 又是 1 << seL4_SlotBits
字节大小,因此CNode 的大小是 1 << (CNodeSizeBits + seL4_SlotBits)
字节。
size_t initial_cnode_object_size = BIT(info->initThreadCNodeSizeBits);
printf("Initial CNode is %zu slots in size\n", initial_cnode_object_size);
size_t initial_cnode_object_size_bytes = BIT(info->initThreadCNodeSizeBits + seL4_SlotBits);
printf("The CNode is %zu bytes in size\n", initial_cnode_object_size_bytes);
打印出的结果为
Initial CNode is 65536 slots in size
The CNode is 2097152 bytes in size
后面就是基于 CSlot 的拷贝、删除等操作。
拷贝 CSlot: seL4_CNode_Copy
seL4_Error error = seL4_CNode_Copy(seL4_CapInitThreadCNode, first_free_slot, seL4_WordBits,
seL4_CapInitThreadCNode, seL4_CapInitThreadTCB, seL4_WordBits,
seL4_AllRights);
删除 CSlot
可使用 seL4_CNode_Delete
或 seL4_CNode_Revoke
。
seL4_CNode_Delete(seL4_CapInitThreadCNode, first_free_slot, seL4_WordBits);
seL4_CNode_Delete(seL4_CapInitThreadCNode, last_slot, seL4_WordBits);
调用权能 invoke
例如,使用 TCB 相关的权能挂起任务。
seL4_TCB_Suspend(seL4_CapInitThreadCNode);