黄瀛:大家好,我是来自英特尔科研技术中心上海的黄瀛,今天我给大家介绍
一下,我最近做的一点工作。今天先对相关的背景做一个简单的介绍。接下来介绍一
下对怎么样增强休眠工作,包括怎么样增加内存的内容,怎么样从休眠的内核中跳回
到原内核中去,怎么样恢复状态,包括写出内存镜像,怎么样通过Kexec实现唤醒的
功能,接下来我们介绍一下简单的结论。
首先简单介绍一下Kexec,它的功能基本上是把Linux内核变成一个能力,它能
够在一个正在执行的Linux系统之中载入另一个内核。它的实现通过两个部分,首先
是一个载入的过程,在这个过程当中,要载入内核的内容,会被载入到软件里面去。
这个可能和最终的目标配制不一样的,因为这可能当前正在使用中,会设置一些启动
的参数,不同的操作系统有不同的需求。另外一个部分就是真正的去执行。这个时候
它要做的工作包括首先会准备设备,基本上准备设备的方式和做关机的方式是差不多
的,就是把设备的工作都停下来。
接下来会转换到物理模式,把分页给关掉,然后执行新的内核。我们从这个图
中可以看到,无论是原来的内核,还是说用Kexec重新执行的内核,它们都是使用了
整个的内存,就是所有的内存,这样的话新的内核就是完全把过去内核的内容全部覆
盖掉了,但是对实现Kexec来讲是没有问题的。
接下来我们介绍一下Kdump,它可以在系统发生崩溃的时候,用Kexec方式把内
存内容写到磁盘里去,这样可以将来对它进行分析,来分析出现问题的原因。它是基
于Kexec来做的实现。它首先在原内核中启动的时候,启动过程中会保留一部分内存
,专为做Domp内核使用。就像这个图中蓝色的部分。被启动的内核也和Kexec不同,
它仅在这一部分指定的内存中运行,而不破坏其他的内核,这可以通过内核的一些启
动命令行参数模式来达到这样一个功能。
这样的话当我们做Kexec的时候,载入的时候,我们就把Sotf配制载入就可以
了。然后再跳转,执行一个Kexec就完成这样一个功能。这样大家可以看到因为原内
核没有使用这一块,目标内核只使用这样一块内存,所以说原内核的内存的内容就保
留下来了,这样我们就可以在Damp内核里面把原来的内容保存下来。这个保存的接口
,为了实现这个保存的功能,内核提供了一个叫VMCall虚拟的文件,用它来访问原内
核内存的内容。
接下来我们介绍一下休眠,休眠是一种电源管理的方式,它基本的内容就是把
设备和CPU的状态保存到内存里面去,然后再把内核里面内存的内容存到磁盘里,然
后就关机,或者是待机的状态,这样来达到省电的目的。等到重启之后再把相应的内
容恢复回来。现在的实现有一些细节,首先休眠过程中会去冻结所有的进程,这主要
是因为当前的休眠的实现要把这个写出,写出内核,写出这个内存镜像的内核,和原
内核是同一个内核,所以说它就是要把其他的进程全部停掉,这样的话让他们不去在
这个写出的过程,再往磁盘上写东西,因为这个时候会造成不一致,磁盘内容的不一
致。
接下来会再一些准备设备,包括把设备安静下来,保存状态,保存一些CPU的
状态,然后把它们写出去,启动的时候把它载入进来,然后拷到目标位置上去,把它
恢复回来,基本上是这样一个过程。现有的休眠的实现呢有一些问题,其中第一个就
是跟现有一些实现重复,主要是和Kexec有一些重复,我们可以看到它在休眠实现里
面包含写出内存镜像到磁盘的过程,其实在休眠当中也有这样一个过程,一个内核里
面对于相似的一件事情提供了两个实现。
那么另一个就是唤醒的时候,把磁盘中的内存镜像载入进来的时候,其实和K
ESC的load有一些重复的。第二个比较大问题,就是对于冻结程序的依赖,这个冻结
主要是有一些问题,所以很多人有不满。接下来还有一个问题就是内存镜像的大小问
题,因为原来休眠的实现中是在把使用的内存拷贝到空闲中,用这种方式准备这样一
个内存镜像,所以这个内存镜像大小,很难超过整个大小的一半,这是比较大的一个
限制。虽然说另外有一个实现解决了这个问题,但是还有很多人认为这个方法不够好
。
接下来我们介绍一下基于Kexec休眠实现。它基本上就是使用Kexec和Keepdam
p,来实现原来休眠的部分。它实现基本的方法首先就像现有的休眠实现一样,去满
足CPU状态的保存和恢复这样一些功能。然后再把这个内存镜像写出磁盘的时候,是
用Keep domp的方式,唤醒是用Kexec load功能,然后再恢复CPU和设备的状态。基本
上就对现有的Kexec和Keepdomp做了一些增强,然后再结合一些休眠的实现,所以相
对来说是比较简单的。
接下来我们看一下让Kexec和Keepdomp实现休眠的功能我们做哪些增强。首先
第一个问题是保留内存的状态, Keepdomp有这样一个功能,但是必须要在启动的时
候保留一部分内存不要使用,这样来讲对内存是一种浪费,还有一个就是它相对来讲
使用和配制起来要稍微麻烦一点。那么我们就看一下我们怎么样实现这样一个方式,
大家看这个图,首先我们和Keepdomp一样,要做写出内核也是在指定的范围内运行,
它采用的方式和Kexec差不多。只用这个范围内的内存,不使用其他内存。另外一个
和原来的差不多,我们要为载入的内核,分配一个配制,就像这个图上蓝色的图一样
,再一个就是对于在目标范围内的,但是又不是载入的其他的页,我们为其中每一个
页都分配一个备份页,就像这里面绿色的部分,这样的话在我们做KESC的时候,我们
就去交换这个目标页的内容和X-space,这样原有的内容就被保存下来了,通过这样
一个方式来完成这样一个功能。
我们会在原内核里面定义一个入口,由它完成一些功能,这个功能很简单,它
把除了目标位置之外的内容恢复回去,就像这个图中的箭头指的再做一次交换,做一
次交换的时候,因为原来我们是把目标范围这样一些内存的内容备份起来了,这样再
做一次交换的话就把它的又恢复到原来的位置上去了,这样原来的内核就又可以在上
面运转了。这具体的实现我们用了一个辅助性的功能,还是用Kexec这样一个方式做
这样一个工作。
下面谈一下保存和恢复状态,这基本上是和现有的休眠的实现是同样的方式,
就是把这些需要保存的状态罗列了一下。大家可能容易忽略的,比如说除了CPU和设
备之外,还有内存之外可能我们还要保存磁盘的状态,可能在PC平台上除了有OS之外
,还有其他的,可能我们需要考虑一下其他的状态要怎么样的,怎么样和它们进行协
作。
写出内存镜像,基本上就是采用Keep domp方式来做的,基本上是利用Keep d
omp提供的接口去访问原内核的内存,把它写出去,另外还使用了一个Make down f
ree,这和Keep domp配套使用的工具,它主要能把一些空闲页踢掉。
恢复这个内存的镜像的话呢,我们采用这样一种方法,把要恢复的内存镜像,
把它当作一个普通的连接内核的方式,把它载入到内核里面去,就像刚才那,把它先
拷到X-Space,然后再把分页关掉,再把它拷回到原来的位置上去,通过这个方式来
完成,所以说这部分的实现可以很简单。
基于这样一个实现的话也有一些问题,我们现在遇到一个问题是和ACPI有关的
问题,这样就是内核对整个系统不是完全的控制,这样跟他的协作的话存在一些问题
,首先是Kexec要求基本上从理论上讲,Kexec要求ACPI应该是可重入的,就是你对A
CPI,调用了ACPI方法在第一个内核里面,它的状态已经发生了一些改变,这时候你
又启动新的内核,这样在新的内核里面又访问ACPI的状态,它可能就又修改了ACPI的
状态,这时候这些状态是怎么样的交互的过程,可能存在一些问题。当然虽然现在我
们在实际做的实验中还没有发现,但是这确实是一个潜在的问题,他们我们考虑过可
能的一个方式,就是说是不是能够把 ACPI的状态,在Kexec也做一些保存,然后在跳
回的时候做一些恢复,通过这样的方式做一些这样的事情,来解决这个问题。
另外就是基于Kexec休眠的实现,和ACPI也有一些问题,ACPI要求在休眠之前
和之后去执行一些ACPI的方法,原来的内核里面都是在一个内核里面执行,现在要把
它分到两个内核里面执行,所以这需要更多的测试。我们现在有一个简单的结论,由
于采用了Kexec和Keep domp实现大部分功能,所以就比原来的休眠实现更简单,也解
决了一些重复的问题。那么对于进程来说,因为它采用不同的内核来写出内存镜像,
所以当驱动程序的问题解决了之后,这应该是可以去掉的,当然这个驱动程序主要是
因为很多驱动程序是假设存在的,以这样的前提去写的,可能这方面还有很多工作要
做。
那么再一个就是它很容易超过一半的系统内存的大小,因为它不需要做拷贝,
来制作内存镜像,可能只是要求系统空闲内存的大小要大于写出内核的所使用的内存
的大小就可以了。我讲的内容基本上就是这些,大家有什么问题吗?
提问者:能不能在Kexec重新加在新内核里,在加载之前重新初始化一编ACPI
。
黄瀛:我们的想法和你这个比较接近,跟你的这个想法有点相近。
提问者:这个内存镜像会不会被压缩呢?
黄瀛:这个压缩的过程是在Domp的过程中进行,因为在原来的位置上嘛,我们
到执行Domp内核里面去,这里面有完整的一个系统,除了内存大小受一定限制之外,
所以说可以完全做各种压缩等等都没有什么问题。
提问者:用这种方法的话会不会比以前快一些?
黄瀛:从理论上讲,如果做一次完整的,第二个内核有一个过程,如果要做这
个完整的过程的话,那肯定是要慢一些的,但是我们也开发了一些优化的方法,来解
决这个问题,就是我们把第二个内核,就是第一次是第二个内核完全的重启,等完成
之后我们把第二个内核也休眠起来,第二次我们就不去做完整的过程,就相当于把写
出的内核唤醒起来,有这样一个优化。
提问者:我不理解,您在再内核拷贝出来期间,如果发生什么写操作的话,怎
么解决呢?
黄瀛:因为是在两个内核里面做的,你在写入磁盘的时候,和原来的内核是两
个内核,原来的内核的内容都在原来的内存里面,是不会碰的。
提问者:但是原来的内核里面的内容在运行?
黄瀛:原内核所有的进程都不会运行了,因为进入到新的内核里面了,原来内
核所有的进程都不再运行了。
提问者:你在做的时候,实际上是起来一个新的内核。
黄瀛:对。现在我们有一些界面方面的问题,我们正在解决一些界面方面的问
题,就是包括内核用户的界面,还有就是如何来保证非常稳定,有一个非常稳定的界
面,我觉得大部分都已经完备了。
提问者:那么我非常支持你们在这方面,我在这方面希望能够祝贺,而且我也
鼓励你们将来在这方面进行更多的尝试。
黄瀛:好的,谢谢大家。