XenBus是通过XenStore协商的一套协议,前端和后端通过XenBus进行协商最终建立起通信, 前端和后端都是状态机,而状态转换的条件就是由XenBus来完成的,本篇将介绍XenBus. 源码可以从Github上得到。
- Grant Table
- I/O Ring Structure
- Event Channel Implementation
- Event Channel Usage
- XenStore Usage
- Write a PV Driver
- Connect to XenBus(本篇)
XenBus
The XenBus, in the context of device drivers, is an informal protocol built on top of the XenStore, which provides a way of enumerating the (virtual) devices available to a given domain, and connecting to them. Implementing the XenBus interface is not required when porting a kernel to Xen. It is predominantly used in Linux to isolate the Xen-specific code behind a relatively abstract interface.(from chapter 6.4[1])
XenBus由于是一个通信协议,因此不是必须要实现的(e.g.XenStore & Console). 使用XenBus能够和Dom0上的Backend进行协商,不过我们同样可以实现自己的协议。
XenStore与Console也属于设备的一种,而这两者就是直接从start_info
获取的,其余的外设则是通过XenStore进行交流.
State Machine
1 | enum xenbus_state |
使用XenBus协议的设备状态有以上这些,其中Reconfigure我们暂不讨论,一般设备不重新配置的话是不需要这个状态的,状态的转换一般如↓:
1 | 183: static int __xenbus_switch_state(struct xenbus_device *dev, |
在xenbus.h
中有所有状态的声明, 由switch_state
进行状态的迁移,switch_state
会通过XenStore接口(Linux中即XenBus接口)向XenStore实时写入目前设备的状态
由此另一端就能通过状态来判断是否是否应该读取某些值,通过这个协议前后端就可以进行协商(告知对方shared page的grant reference等)
而两端也都会在对方Xenstore的key上注册watch来监控变动,这样当一方状态改变时另一方就能迅速做出相应。
一般来说我们会把尽可能多的工作交给back来完成, 这样Guest的driver就可以尽可能简化, 而共享页等分配则交由Guest来做, 当然自己的Driver也可以不这么做..而前后端的状态会互相影响:
一般Back初始化后front才开始初始化, (front可能会从xenstore读一些关于back的信息),back的初始化会用到front的一些数据(grant ref等), 因此在front初始化完成前back会进入Initwait等待front向xenstore中写入信息。之后当guest连接到bus后back也会连接到bus上,此时driver就可以正常工作了。
当任何一方断开时另一方也会断开。
Add State to Driver
我们现在给前一篇完成的Driver中加入XenBus的状态:
1 | /* We set up the callback functions */ |
主要内容就是加入otherend_changed
函数并在里面根据另一端的状态切换本端的状态。顺便提一下activate.sh
需要给domU和dom0的Key加入读写权限:
1 | # Make sure the domU can read the dom0 data |
Demo
1 | # DomU: |