2007年6月21日星期四
Stay in Unattended mode(written by Mike)
PowerPolicyNotify(PPN_UNATTENDEDMODE, TRUE);
Then call
PowerPolicyNotify(PPN_POWERBUTTONPRESSED, 0);
Now handle the call. You need to be calling SystemIdleTimerReset(); every 30 seconds to keep the system from falling asleep while you're processing the call.
When the call is over, do:
PowerPolicyNotify(PPN_UNATTENDEDMODE, FALSE);
The first PPN puts the system into a state where, if the power button is pressed, it will turn the screen off but not suspend.
The second PPN simulates the press of the power button. Assuming the screen was on at the time, this will tell the system to suspend, but will instead go to the Unattended (screen off) state because of the first call. (If the screen was off when you did the PowerButtonPressed, it would turn the screen on.)
When you're done with the call, the last PPN tells the system to suspend immediately (as long as there isn't another app in Unattended).
SD卡关于WINCE睡眠的思考
On most devices, the SD hardware is powered down when the system suspends. So it needs to be re-initialized on wakeup. Then, after it is initialized, it needs to find the SD card and mount it. Depending on the SD bus hardware and the particular SD card, this process can take a few seconds.
在大多数的设备上,当系统进入睡眠时,SD设备是断电的。因此当系统醒来时,它需要重新的初始化。很自然地,初始化后,要查找SD卡和挂装文件系统。由于SD设备和SD卡的不同,这个过程需要一些时间。
由此想到以下的测试要求是不合理的:
1.SD卡复制文件时,susend和wakeup系统,不能要求他还能续传
2.Media player在播放SD卡上的音乐文件时,susend和wakeup系统,不能要求还能继续播放
2007年6月19日星期二
Windows Mobile 5 虚拟内存空间危机
Windows Mobile 5的虚拟内存模型如下图:
我们会看见这样的概念:kernel space 和 user space。看似简单,你真的理解么?分析这样的memory space概念的时候一定分清视角,通俗说就是你是以user进程的角度,还是以微软操作系统内核的角度看这个空间。这点非常重要。不信你试试看。
0x8000,0000到0xFFFF,FFFF这个叫内核空间,也就是只有内核代码可以用这样的地址,他们是高特权级的区域。你的应用程序是访问不到的。如果你要“硬”来,操作系统一定会把你destroy掉,并给你一个类似非法访问的警告提示。除非你是“黑客”,用类似“缓冲溢出”等攻击方法来访问。
那么对于0x8000,0000以下的空间,叫做用户空间。什么?你做就知道了?!哈哈!那我问你,用户空间是不是只有用户程序可以访问的空间?你要是回答是,那就错了。用户空间是用户程序可以访问的空间,但不是“只有”。内核是老大,他当然也可以访问。所以你看,我们定义user space的概念一般只是针对user来说,而定义kernel space只是针对kernel来说,如果你只是单单把user space和kernel space放在一起,实际上没什么可比性。
小总结一下,kernel可以访问整个4GB空间,而user“最多”只能直接访问下2GB空间。我这里又多强调了一个“最多”。下面将详细讲解。
“最多”也就是说用户程序不能整个空间都是他的,一个多任务分时操作系统上同时有很多的用户的程序在“奔跑”,而且彼此独立,互不打扰。内存空间这样宝贵的资源,内核不可能让某个进程独占,因此,Windows Mobile5将下2GB空间均匀划分成64块,每一块32MB,并且slot0~slot32用于用户程序,slot32-slot63用于shared memory,所以WM5最多能有32个进程同时在运行。我们可以看见,每个单独的process是有可怜的32MB的大小。这个数值才是我们真正该关心的东西。每个进程的内存是不允许其他空间随便访问的。可怜可怜,你只有有32MB可以“使用”。“使用”这个概念再落实一下,就是如你调用VirtualAlloc()这样的内存分配函数。
我这篇文章叫“危机”,不是光介绍一下这些概念。想想,像device.exe这样的“进程大户”,身上挂装了n多的DLL,而且每个驱动程序都要类似调用VirtualAlloc的函数来映射寄存器空间,也就是CPU的整个寄存器空间几乎都要映射到这个狭小的32MB空间里,自己本身还有很多的代码与数据要占用空间,这个进程真是很吃力呀。随着SOC(system on chip)的茁壮成长,一个chip里集成的module数量越来越多,随之而来的寄存器的增多,也就是寄存器组空间的增大,Windows Mobile5将不再可以使用。
幸好2007年我们迎来了Windows CE 6,虚拟空间的问题得以解决。可是微软相继发布的CrossBow主要是UI的变化,内核依然采用windows CE 5。不知什么时候微软会发布使用CE6内核的Windows Mobile。
我们现在还要继续使用Windows CE5 kernel,那就要想办法解决这个问题。
前面提到slot32-slot63用于shared memory,如果能使用这块空间,那么虚拟内存不足的问题就可以解决。微软告诉我们mapped file是使用这块空间的,所以解决方案自然是
h_map=CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, Size, NULL);
VirBase=MapViewOfFile(h_map, FILE_MAP_WRITE, 0, 0, 0);
这样分配下来的虚拟地址会在0x4200,0000-0x7E00,0000区域内。此时只有虚拟空间被分配,实际的物理内存还并没有映射。因此这个时候你不能类似这样:
*(volatile DWORD *)VirBase=123;
写内存,这个动作会分配实际的物理内存,从而直接导致下面的VirtualCopy的失败。
这样虚拟空间有了,实际的物理内存可以这样映射
VirtualCopy((void*)VirBase, (void *)(PhyBase >> 8), fbSize, PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL)
这个三个函数的结合使用,使我们可以充分利用user memory 的空间。
2007年6月13日星期三
Windows Mobile文件系统相关注册表设置
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\SMFLASH]
"Prefix"="DSK"
"Dll"="ONDisk.dll"
"Index"=dword:1
"Order"=dword:10
"Profile"="SMFLASH"
"IClass"="{A4E7EDDA-E575-4252-9D6B-4195D48BB865}"
"BmlVolumeId"=dword:0
"BmlPartitionId"=dword:3
[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\SMFLASH]
"DefaultFileSystem"="IMGFS"
"PartitionDriver"="mspart.dll"
"AutoMount"=dword:1
"AutoPart"=dword:1
"AutoFormat"=dword:1
"Name"="Microsoft Flash Disk"
"Folder"="Storage"
[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\SMFLASH\IMGFS]
"MountHidden"=dword:1
"MountAsROM"=dword:1
"XIP"=dword:0
[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\SMFLASH\FATFS]
"Flags"=dword:10
"FormatTfat"=dword:1
"CheckForFormat"=dword:1
"EnableWriteBack"=dword:1
"MountAsBootable"=dword:1
"MountAsRoot"=dword:1
红色的是经常被质疑的部分,他们虽然在微软的document上可以找到相关解释,可是还是有很多歧义,让我们一起仔细看看。下面我会用到很多PC的概念来帮助大家理解。
第一段代码是说明“硬盘”驱动是那个DLL。Profile键值说明profile的名字,也就是【HKEY_LOCAL_MACHINE\System\StorageManager\Profiles】之后跟着的名字,这个名字你随便取,只要不超过7个字符都可以。其实profile可以理解为在“硬盘”驱动之上的软件层,属于文件系统这个领域的概念。而第一段是驱动程序领域的概念。
第二段是这个profile的总体的信息,他一定会有分区的概念,所以我们需要mspart.dll来识别分区信息。
"AutoMount"=dword:1
"AutoPart"=dword:1
"AutoFormat"=dword:1
这几个你就一起用,没关系的。我知道你担心什么。那就是担心分区的内容会不会每次重启都会重建,分区内容会丢失。实际上不会的。Autoformat是当发现分区的文件系统没有格式化时,才回去format,反之,如果已经formated,那么就不会有任何动作。Autopart是在你的profile没有分区时,系统自动帮你分区,不过他没有那么智能,只能将整个profile分成一个区,从头到尾。当然同上,如果你已经有分区信息,系统不会做任何动作。Automount是如果分区没有安装,就会自动安装。这3个键值,你就一起把他们加上,肯定没问题。
第三段定义了profile之上的特定分区imgfs分区,这是一定要有的分区。MountHidden是将这个分区安装为不可见。这样你在资源管理器里就不会看见这个目录。MountAsROM是以只读方式安装,这样分区的文件是不可写的。
第四段代码是真正的用户空间,是fat文件系统。FORMATTFAT是强制以tfat文件系统格式化,tfat比fat更加的强壮。CheckForFormat键值是可选的,加上之后,这个分区在每次重启是系统都会用
IOCTL_HAL_QUERY_FORMAT_PARTITION 的ioctl来检查是否需要格式话。如果没有这个键值,文件系统就不会调用这个ioctl。
"MountAsBootable"=dword:1
"MountAsRoot"=dword:1
这两个键值一般都一起用,就是指明是该分区是root file system。
好了,到此就基本说完了。如果有什么问题可以mail我。