Chinaunix首页 | 论坛 | 博客
  • 博客访问: 244658
  • 博文数量: 32
  • 博客积分: 2033
  • 博客等级: 大尉
  • 技术积分: 354
  • 用 户 组: 普通用户
  • 注册时间: 2007-06-10 01:53
文章分类
文章存档

2011年(2)

2010年(16)

2009年(13)

2008年(1)

我的朋友

分类: LINUX

2010-03-03 12:02:42

关于suspend和resume
不想从kernel角度来说了,这个如果要说的话,需要单独拿一个驱动代码来讲才比较好。
但是还是有其他的事情,之前我看的是比较老一点的内核的代码,现在应该有一些变化,
但是大框架应该没变,之前看代码的时候是有记录的,记录是一个好习惯,虽然我一般也是写了之后,
未来再也不会看,但是写一遍之后印象还是深一些,记得大概是两年前的一个项目,当时遇到一些很奇怪的问题,
当时是有记录的,后来有人问我,播放声音的时候系统挂掉,我知道有那么一个问题,但是不记得当时是怎么解决的了,
后来回去grep了一下当时的记录,都是txt文件,还是找到关键字了,这些很多东西都是硬件相关的,平台相关的东西,
一旦换了之后就再也不去解除,忘记的快了。记录不记录,几年之后,大家的差别也就出来了。


想起说这个suspend和resume的问题,主要是因为xorg里面也是要处理这些事情的,如果处理不好。图形系统就会挂起,
看起来很奇怪,但是图形系统就是这么脆弱,但是图形系统就是有一套规范的,如果suspend和resume中不按照规则来办事,
xorg就挂起



所以简单说一下kernel里面的suspend和resume,以后有时间再从kernel里面找一个驱动来说明。

现在的suspend和resume框架是这样的,每个kernel module都必须支持suspend和resume。
在我们echo mem >/sys/power/state
的时候,kernel就会进入suspend状态,系统将应用程序的状态都保存在内存里面,然后suspend其他的设备,其他的设备都断电了,只有内存还供电。

echo disk >/sys/power/state
这个是把东西保存到硬盘的,然后关闭所有设备。彻底断电了,和上面有所不同,也就是我们所说的hibernate
实际这个东西是上面的内存的一个镜像,把这个内存镜像存储在一个swap分区的。swap本来就是做存储用的。和普通的文件系统不同。
swap是单独开辟出来做虚拟内存用的,hibernate的时候就是把系统当前运行环境保存到swap里面,然后系统断电。
等到下次开机的时候在linuxrc里面(就是我们的ramdisk里面最先被执行的脚本,可以是其他名字,这个名字是通过cmdline指定的,比如init=/linuxrc等等)
脚本可以判断是否有hibernate的镜像,然后再装载这个镜像到内存里面,

简单的说就是这么理解。

但是实际上,开机还是有很多工作要做的,记得大概是做到early_init??不记得了需要查一下代码,也就是说硬件初始化,还有一些基本的初始化还是必须的,
大概是做了这些之后,就会去调用各个模块的resume的函数。

当suspend的时候会freeze所有的进程,然后调用驱动模块里面的suspend函数,
如果某个模块没有suspend函数,但是这个模块正在使用,或者说这个模块有suspend函数,但是suspend函数执行失败了,
这个时候系统就会休眠失败,尝试resume。

如果系统suspend失败或者resume失败,肯定是kernel module的问题。要么是模块不支持suspend,resume或者是他们的函数执行失败。


要查看系统支持那种方式

ailantian@vax:/tmp/lk/123$ cat /sys/power/state
mem disk
ailantian@vax:/tmp/lk/123$


并不是所有的系统都支持hibernate的,pc支持,是intel有一个规范,就是不同的cpu sleep状态,ACPI 规范。
但是这个是基于pc的,pc上面的电源管理都是基于这个的。
http://acpi.sourceforge.net/documentation/sleep.html



关于什么是ACPI,kernel里面是怎么实现的,ACPI是在BIOS里面支持的,
开机的时候kernel获取这个表,然后对应内核函数,ACPI的设计就是操作系统可以更方便的去操作电源管理。
kernel里面是需要按照规范来解析这个格式的。

acpi_table_parse

代码
kernel/drivers/acpi

简单眇了一下,现在table的解析主要还是在tables.c system.c里面。
但是注意这个只是intel pc和类intel pc平台才有的(比如amd的芯片)
这里不写了,找以前写的文档也难找,不知道多少年前看的代码了,啥时候有空再看看,记录之后再写。

ailantian@vax:/proc/acpi$ ls
button  dsdt  embedded_controller  fadt  fan  info  power_resource  processor  sleep  thermal_zone  video  wakeup
ailantian@vax:/proc/acpi$







说多了,回来xorg,

当resume的时候,有一些driver会乱发消息,比如SIGIO,或者由于设备没有初始化好,设置了一些特别的状态,
就会导致上层判断失败,有时候就会进入无限循环,有时候会阻塞,驱动不健壮的话,上层是不知道的,上面假定下面的驱动足够健壮,
我们也假定我们可以正常进行一些操作,我们设置属性,下面不要block或者hang,但是这个时候有可能就是在resume过程中,或者suspend的过程中
底下的驱动一定要考虑到这个问题,就是在关键函数里面的时候(suspend,resume)有人设置属性或者其他操作的时候的状况

Xorg的输入系统是如何支持suspend和resume的?
Xorg如果读取一个设备失败的话,会反复尝试,也就是说当resume回来也不怕,xorg如果发现设备有故障会使用驱动初始化的时候的TmierSet
去重新打开这个设备文件,欲知详情可以看看xf86-input-evdev等等的代码。
ailantian@vax:~/soft/xorg/ex/xf86-input-evdev-2.2.6$ ls
autogen.sh    COPYING       cscope.out  Makefile.am  README  tags  xorg-evdev.pc.in
configure.ac  cscope.files  include     man          src     test
ailantian@vax:~/soft/xorg/ex/xf86-input-evdev-2.2.6$
ailantian@vax:~/soft/xorg/ex/xf86-input-evdev-2.2.6/src$ ls
draglock.c  emuMB.c  emuWheel.c  evdev.c  evdev.h  Makefile.am
ailantian@vax:~/soft/xorg/ex/xf86-input-evdev-2.2.6/src$



                    pEvdev->reopen_timer = TimerSet(pEvdev->reopen_timer, 0, 100, EvdevReopenTimer, pInfo);



当suspend和resume的时候xorg会有leaveVT和enterVT的操作。

VT是linux用的比较多的操作。之前好像写过这样的文档,主要是关于console,tty, vt,fbcon之间的关系。
Splash是需要做vt 的操作的。
简单说一下从上层来讲,当vt切换发生的时候应用程序会受到信号,
比如程序初始化的时候设置一下,当我成为active console的时候请kernel发送什么信号给我,我变成inactive console的时候kernel发送什么信号给我。
设置完之后,当vt切换的时候,该应用就会受到消息,就知道vt切换发生了,简单点可以参考下面文档

都是走ioctl的。
Xserver也是需要这个机制的,当xserver起来的时候会把自己设置成active的,这样别的vt的输出是不会到屏幕上的,
关于console的输出,比如我们在vt6执行应用程序,我们在程序里面printf的时候,也会在console上面输出。pc上面一般是vgcon,但是如果启动参数里面有vga=792这样的参数的
话,我们使用的是fbcon。但是我们切换到vt7(xserver目前一般是这个,可以设置)的时候,他们也还在输出,只是不会刷新到屏幕上面,实际上我们屏幕只有一个,
vt6变成了inactive了。

vt切换现在看来是一种不太可靠的设计。而且很多人也说他不可靠,简单说一点ctrl+alt+Fx来切换,是在两个图形系统之间切换,按键事件处理就不太可靠
之前tty子系统的人还和linus闹矛盾(linus指责tty维护不力),tty这边的问题还是比较多的。


图形系统电源管理
是console下面省电还是xserver图形系统下面省电?
大家可能认为console下面省电,但是实际上,是xserver下面比较省电,xserver的框架里面电源管理做的工作更多。
而fb只是一个最基本的驱动,电源管理是很少的。好像只有一个简单的blank的操作,xserver可以知道所有的输入事件,所以在合适的时候就会进入screensaver或者
调低gpu的频率,关闭不需要的端口比如hdmi电路等等,关闭输出信号,降低framebuffer的clock和刷新频率,或者关闭等等
。xserver管理电源更高层,更复杂一些,功能也更多一点,策略也更多一点。

这些kernel也可以做,但是没啥用。没有人单独跑一个kernel,还有就是kernel里面开发限制比较多,klibc,还有就是kernel本身是一块,都是一个空间(可以理解为一个进程空间)
kernel里面尽量只提供该提供的东西,只做该做的事情,至于策略,都放在用户空间的好。


Xserver最近的大改动还是input子系统(1.7系列),主要就是mpx的部分,改动多,bug多,稳定性大不如以前。
开发列表里面也都是充斥着hang,crash的问题。


Xserver对touchscreen的支持不太好,因为好像很少有人pc上面是用的touchscreen的。

阅读(2008) | 评论(0) | 转发(1) |
0

上一篇:Xorg的一些问题和随想

下一篇:graphic camera

给主人留下些什么吧!~~