设为首页 收藏本站
查看: 3052|回复: 0

[经验分享] Qemu-KVM Guest OS Time Tick Source

[复制链接]

尚未签到

发表于 2015-12-24 14:37:35 | 显示全部楼层 |阅读模式
还是先来看一下Qemu用户态模拟时钟是从哪里开始初始化的。代码路径如下图所示,在main
中调用init_timer_alarm开始。还是那句话,Qemu模拟时钟是软件的,不能像硬件时钟那样自
己产生时钟计数,所以必须要求助于host的各种timer服务来提供实际时钟。Qemu在vl.c定义了
一个全局数组alarm_timers[],里面定义了几种host timer服务的封装实例,有dynticks, hpet, rtc。
这三种timer服务是Linux内核提供给用户程序使用的。下面看Qemu是如何具体利用这些服务的,
就能有更深的认识了。

如果是选用dynticks,那么在init_timer_alarm中调用t->start即dynticks_start_timer。dynticks_start_timer首先用sigaction注册SIGALARM信号的handler为host_alarm_handler,然后调用timer_create创建一个
时钟。这就很清楚了,timer_create实际上就属于Posix Timer API。应用程序创建了一个Posix Timer后,
一旦timer到期,那么内核将给调用进程发送一个SIGALARM信号,应用进程通过signal handler再去做处理。

QEMU timer emulation path:main(vl.c) ---> init_timer_alarm(vl.c) ---> dynticks_start_timer ---> sigaction(SIGALARM, host_alarm_handler)
--> timer_create(or ---> hpet_start_timer ---> open(/dev/hpet) ---> enable_sigio_timer --> sigaction(SIGIO, host_alarm_handler)


刚开始仔细一想发现不对了,在内核模拟时钟时,是调用hrtimer_init和hrtimer_start来初始化hrtimer,并且
可以指定一个回调函数,一旦hrtimer到期,内核会调用回调函数,为什么这里不能这样,而只是发送一个信
号呢? 其实问题很简单,内核调用回调函数是在内核空间调用,所以内核模拟时钟可以注册回调函数。但是,
提供给用户程序的timer API当然不能让用户程序直接注册回调函数,不然启不是允许用户函数到时可以在内核
态下运行了?因此,对于用户程序,当timer到期后,只能是发送一个信号给用户进程,进程实际上用回调函数
注册为signal handler。

Posix Timer是怎样实现的呢?在hrtimer.txt中说了,Posix Timer是基于hrtimer机制实现的,我想大概是这样的:
用户进程调用timer_create创建Posix Timer,实际上内核用调用hrtimer_init初始化一个hrtimer,当hrtimer到期时,
内核执行其回调函数,回调函数将会发送一个SIGALARM给用户进程。

结合以上论述,当dynticks timer到期后,内核发送一个SIGALARM信号给Qemu进程,之前介绍过,Qemu进程
block了SIGALARM信号,信号是由创建的signalfd去接受;之后,io thread用select检测到signalfd read ready,
然后就调用sigfd_handler;sigfd_handler根据signal number,调用相应的handler,就是之前用sigaction注册过的
host_alarm_handler。

可以看出,dynticks实际上是内核提供的软件timer服务,那么hpet和rtc又是怎样的呢?通过研究hpet_start_timer,
发现原来这里是直接去调用hpet driver,使hpet硬件直接产生一个Qemu需要的时钟源。当hpet timer到期时,hpet
硬件发送一个interrupt给host,host hpet driver handler发现这个中断是由Qemu进程"引起"的,所以发送一个SIGIO
信号给Qemu进程。同样,在hpet_start_timer调用的enable_sigio_timer函数中用sigaction注册host_alarm_handler
为SIGIO信号的handler。rtc也跟hpet是一样的,实际上是去调用rtc driver,不用多讲了。

因此,可以发现dynticks是利用软件timer提供时钟计数,而hpet和rtc是直接利用硬件提供时钟计数。现在可以总结
一下Linux下的各种timer服务了:

首先,内核态程序可以直接使用hrtimer API来使用timer,可以到期时可直接执行回调函数。至于hrtimer可以使利用
hpet,也可以是利用local APIC timer去实现的。

其次,用户态程序可以有三大类timer服务——第一类是,nanosleep()、sleep()这样的系统调用,内核
实际上在内核创建一个临时的timer,当到期时将用户进程唤醒;第二类是,Posix Timer API,内核实现
上是用hrtimer来实现Posix Timer的,当到期时将发送一个SIGALARM信号给用户进程;第三类是,
/dev/hpet和/dev/rtc,即直接利用硬件timer,因为这些硬件timer可以支持很多个不同频率的timer,所以
用户进程可以直接使用其中的一个,当到期时内核将发送SIGIO信号给应用进程。

最后说一下,这里还有个重要问题没有讨论,就是Qemu用户态模拟时钟如何将产生一个虚拟时钟中断,将其最后
注入到guest里面去。这就要从host_alarm_handler开始研究

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-155796-1-1.html 上篇帖子: KVM虚拟机代码揭秘——QEMU的PCI总线与设备 下篇帖子: qemu-kvm savevm/loadvm 流程
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表