xen事件通道机制及其实例

    事件通道机制是xen用于Domain和Xen之间,或者Domain和Domain之间的异步事件通知机制。事件通道在xen中应用非常广泛,像物理中断,虚拟中断以及域间通信等均是通过事件通道实现的。
    根据用途划分,事件通道一般分为四类:域间通信,域内通信,虚拟中断,物理中断。域间通信主要用于Domain与Domain之间通信,或者Xen与Domain之间通信。域内通信就是同一个域内不同VCPU之间通信。物理中断与虚拟中断都是绑定中断源,实现Xen的中断。
    Xen在内核态和用户态代码中都封装了很多事件通道相关的操作函数,像分配通道,绑定通道,置pending位等,如果需要可以自己研究源码。『Xen虚拟化技术(石磊 邹得清 金海)』一书中对事件通道的原理,函数,数据结构讲解的比较全面,可以参考。
    我这里主要是简单讲一下我自己实现的Domain0与Xen进行通信的例子。

    因为项目需要,我需要实现Xen给Domain0发送事件通知,Domain0收到事件通知后就执行某些操作。这里使用域间通信来实现,大概的流程就是Xen内核态代码中先为Domain0分配一个事件通道端口,用户态通过超级调用获取这个事件通道,并进行通道绑定。然后用户态陷入循环等待中,等待Xen内核发来事件通知,收到通知后就执行预先写好的那部分代码。

具体代码:
内核态分配通道端口:
//save_domid这里指定为0
int event_channel_port=alloc_unbound_xen_event_channel(current, save_domid, NULL);

内核态分配了端口后,传到用户态,即event_channel_port。
用户态进行绑定:
xc_evtchn *xc_event_iface = xc_evtchn_open(NULL,0);
if(!xc_event_iface)
{
    PERROR("Could not open interface to libxc event channels");
}


int event_port = xc_evtchn_bind_interdomain(xc_event_iface, DOMID_SELF, event_channel_port);
if(event_port != -1)
{
    PERROR("event_port is: %d",event_port);
}
else
{
    PERROR("Could not bind xen port to local port");
}


用户态绑定后,可以设置一个循环等待事件通知的到来,当然根据自己的需求进行修改。

while(1)
{
    int pending_port = xc_evtchn_pending(xc_event_iface);
    if(pending_port == event_port)//收到事件通知
    {			
	if(xc_evtchn_unmask(xc_event_iface, event_port) == -1)
	{
		perror("Could not unmask event port in loop");
		break;
	}
	//下面就是自定义的收到事件通知后的处理代码
        //。。。。。。。。。
        。
        。
        。
        。
    }
    else
    {
	PERROR("Unknown event port pending: %d", pending_port);
    }
}//end while
//事件通道使用完了后进行解绑释放
xc_evtchn_unbind(xc_event_iface, event_port);
xc_evtchn_close(xc_event_iface);
free(xc_event_iface);

内核态发送通知代码如下:
void notify_via_specific_xen_event_channel(struct domain *ld, int lport)
{
    struct evtchn *lchn, *rchn;
    struct domain *rd;
    int            rport;


    spin_lock(&ld->event_lock);


    if ( unlikely(ld->is_dying) )
    {
        spin_unlock(&ld->event_lock);
        return;
    }


    ASSERT(port_is_valid(ld, lport));
    lchn = evtchn_from_port(ld, lport);//bind local event channel
    ASSERT(consumer_is_xen(lchn));


    if ( likely(lchn->state == ECS_INTERDOMAIN) )
    {
        rd    = lchn->u.interdomain.remote_dom;
        rport = lchn->u.interdomain.remote_port;
        rchn  = evtchn_from_port(rd, rport);
        evtchn_set_pending(rd->vcpu[rchn->notify_vcpu_id], rport);
    }


    spin_unlock(&ld->event_lock);
}


void notify_domu_before_page_modify(void)
{
    struct domain *ld;
    ld = rcu_lock_domain_by_id(save_domid);
    notify_via_specific_xen_event_channel(ld,event_channel_port);
    rcu_unlock_domain(ld);
}


notify_domu_before_page_modify();


    这样,Xen就可以向Domain0发送事件通知了。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值