代码改变世界

Windows Embedded CE 6.0 Internals (1) Kernel Overview

2009-07-18 23:49  王克伟  阅读(...)  评论(... 编辑 收藏

最近在学习Windows Embedd CE 6.0和Windows桌面系统内部一些知识,这篇文章是对部分内核知识的整理和总结,跟各位博客园的朋友分享。Windows Embedded CE 6.0是非常优秀的嵌入式系统(不是做广告哦^^),对其内核的学习对我们开发、移植驱动和应用程序,对开发、移植嵌入式系统都非常有好处。最好的学习方式就是看源码啦,直接看源码有点困难,所以这篇文章就是帮你更好的看源码的。欢迎各位园友的批评指正。

1.Windows Embedded CE 6.0系统的一些关键特性

★32位多任务操作系统

★多任务抢占、硬实时

★支持的处理器体系结构:ARM, x86, SH4, MIPS

★组件化

★Based on Win32 API Set,桌面系统的一个扩展子集,超过2000个函数可以使用。

★标准的Portable Executable(PE)文件格式

另外需要注意的是Platform Builder开发工具集成的Visual Studio中,作为后者的一个插件。开发Windows Mobile 6.x时使用的还是独立的Platform Builder for Windows Mobile,相信到Windows Mobile 7.0时会有所变化。

作为通用性桌面操作系统的Windows XP取得了巨大的成功,关于其系统特性请看这。所以微软又推出了Windows XP Embedded。与Window XP Embedded需要借助第三方插件才能实现实时操作系统相比,Windows Embedded CE 6.0是具有32 位本机实时支持的统一内核的。微软另一款具有本机实时支持统一内核的嵌入式操作系统是Windows Embedded NavReady。更多Windows Embedded系统看这里

目前Windows Embedded CE 6.0到目前为止最后一次较大更新为R2(2007年11月15日),其它小更新看这里

 

2.系统架构

下图为Windows CE 5.0系统架构,与下下6.0的架构图相比,我们发现:

(1).5.0时的NK.EXE被分为6.0的NK.EXE(交给OEM开发)和Kernel.DLL(微软开发)。

(2).驱动分成内核态和用户态。

(3).从图上看不出来的内存架构变化。

image

以下为Windows Embedded CE 6.0系统总架构:

image

以下为更详细的架构图,结合上图我们可以看到:

1.OEM商主要承担OAL模块(包括:NK.EXE和Bootloader)以及内核态驱动的开发。

2.其实从现在的市场来看OEM商有时也会负责应用和用户态驱动的开发。

注:ISV(Independent Software Vendors):独立软件开发商。

image

对上图中的用户态进程进一步了解:

Shell, provides the user with an interface to the objects necessary for running applications and managing the Windows Embedded CE operating system on a target device.

ServicesD.EXE is a process that supplements the Udevice.exe process. ServicesD.exe provides enhanced loading capabilities such as support for starting, pausing, and stopping services.

 

内核态进程及DLL

FILESYS.DLL, responsible for the initialization sequence, object store, registry, CEDB databases, device notifications and other miscellaneous tasks.

FSDMGR.DLL, esponsible for managing file systems, filters, and the storage manager.

GWES.DLL, Windows Embedded CE 6.0 combines the Microsoft Win32 application programming interface (API), user interface (UI), and graphics device interface (GDI) libraries into the Graphics, Windowing, and Events Subsystem (GWES) module. GWES is the interface between the user, your application, and the operating system (OS).

Networking DLLs, NDIS based networking services.

DEVMGR.DLL, the Device Manager is loaded by the kernel, it runs continuously, and it manages loaded device drivers and their interfaces. When the Device Manager loads, it also loads the I/O Resource Manager to read a list of available resources from the registry.

KITL.DLL is Optional.

K.COREDLL.DLL, DLL Kernel version of COREDLL.

KERNEL.DLL - The core operating system (OS) services consist of the Windows Embedded CE 6.0 kernel and other features common to all Windows Embedded CE 6.0 OS designs. Core OS services enable low-level tasks, such as process, thread, and memory management.

 

3.中断机制

下图为中断模型:
(1).设备发起一个硬件中断。->
(2).内核(Kernel.DLL)响应该中断,并call对应的中断服务例程(ISR)。->
(3).中断服务例程快速处理该中断。->
(4).驱动中的中断服务线程(IST)被通知处理该中断,这里内核使用Event通知IST。

image 

这个过程中涉及到的ISR和IST都会处理中断,但有所不同,前者的中断级别更高,所做的工作也很简单,而后者做主要的处理工作。具体请看以下的介绍。

"Real-time applications use interrupts to respond to external events in a timely manner. To do this, Windows Embedded CE 6.0 breaks interrupt processing into two steps: an interrupt service routine (ISR) and an interrupt service thread (IST). The ISR runs immediately to identify and mask the interrupt, and perform any high priority tasks. The corresponding IST is a normal system thread (although typically of high priority) and can perform the bulk of the handling that is not time critical. This two stage model allows the operating system to maximize the amount of time the system is able to respond to other high priority interrupts.

The kernel is able to handle a total of 64 interrupts from external sources, some of which are predefined (e.g. system timer interrupt, real time clock etc). Devices that have more than 64 interrupt sources that need to be exposed (rare) must implement a mechanism to share interrupt identifiers. Typically this is done by multiplexing related interrupts together in the ISR, and demultiplexing them in the IST.”

关于中断在此就介绍这么多,更详细的内容等我慢慢消化了再介绍。

 

4.线程、线程调度、线程同步

线程是被系统独立调度和分派的基本单位,当系统创建一个进程时,至少会存在一个线程(主线程)。所以进程可以被理解为一个壳子。关于线程更多基本知识在此略去。

以下为Windows Embedded CE 6.0的线程各优先级,0优先级最高,255优先级最低:

Priority

Component

0 - 96

Typically reserved for real-time drivers

97-152

Used by the default Windows Embedded CE–based device drivers

153-247

Typically reserved for non-real-time drivers

248-255

Mapped to other non-real-time priorities

 

应用程序一般运行在248-255优先级,被创建的线程默认优先级为251。

另外我们要注意的一个很重要问题是优先级反转(Priority Inversion)问题,比如现在有三个优先级不同的线程A、B、C, A的优先级最高,B次之,C最低。其中A和C需要的资源部分相同。处理器当前执行线程C,比C优先级更高的B有可能打断C而进入运行状态,这样C占有的资源什么时候释放就是一个未知的时间。A只有在C释放了它所需要的资源后才能被调度,A被阻塞的时间也是未知的。这样,低优先级的B先于高优先级的A被调度,优先级发生了逆转。

这个问题在XP里面不是一个严重的问题,最多A被多阻塞了一段时间。但是,在实时系统里面,特别是硬实时系统里是个很严重的问题。这个问题的解决方法一般有两种,Windows Embedded CE 6.0采用的后一种方法,从下面的图可以看出优先级反转是怎样的。

"Single Level and Fully Nested. In the Fully Nested Mode the OS will walk through all threads blocked and keep boosting each one until the high priority thread can run. This prevents an entire class of deadlocks. Unfortunately it also means an O(n) operation with pre-emption turned off while the scheduler figures out how to get everything unblocked to keep things going. This is a major problem for real-time systems that need deterministic response times.
In order to support hard real-time systems WindowsCE 6.0 uses a single level handling of priority inversion. That is the OS will boost only one thread to release a block. In this scenario the OS will boost the priority of the low priority thread to the priority of the high priority thread until it is able to release needed resource. This is It is therefore the responsibility of the developer to structure code such that deadlocks are avoided. “

image 

更多相关知识请看维基Embedded网站

 

线程相关API

CeSetThreadPriority/CeGetThreadPriority在CE中可以访问整个256个优先级。

SetThreadPriority/GetThreadPriority是遗留下来的函数,在新版本CE系统中仍然可以使用,但是只能访问最低的8个优先级(248-255)。

Sleep(n)至少挂起n毫秒。

Sleep(0)放弃时间片,执行其它线程。

SleepTillTick挂起线程直到下一次系统tick。

WaitForSingleObject阻塞直到指定的内核对象被置为有信号状态。

WaitForMultipleObjects阻塞直到指定的内核对象集(大于等于1)被置为有信号状态。

 

线程同步

被用于线程同步的对象有很多种:临界区(Critical Setions)、互斥体(Mutexes)、信号量(Semaphores)、事件(Events)、Interlocked Fuctions,这里对此进行简单的介绍,关于更详细的资料(比如临界区和互斥体的本质区别以及性能比较)请从网络上查阅,比如这里
在CE 6.0系统中每个同步对象都有自己独立的名字空间,比如一个空字符串"”被作为一个名字对象处理。在桌面系统中所有同步对象是共享名字的空间的。

1.Critical Sections

使用临界区的好处是,当你需要的资源不被其它线程竞争时是不会进入内核的,所以在同个进程里,并且很少的资源竞争存在时,使用临界区会更好。

InitializeCriticalSection初始化临界区数据结构。

EnterCriticalSection 线程会阻塞一直到取得临界区的所有权。

TryEnterCriticalSection 尝试取得临界区的所有权,不会造成线程阻塞,如果当前竞争存在将会失败。

LeaveCriticalSection 释放临界区的所有权。

DeleteCriticalSection 清理资源。

2.Mutexes

CreateMutex 创建命名的或未命名的互斥体对象。

A handle to the mutex object indicates success. If the named mutex object existed before the function call, the function returns a handle to the existing object, and GetLastError returns ERROR_ALREADY_EXISTS. Otherwise, the caller created the mutex.

NULL indicates failure. To get extended error information, call GetLastError.

Non-blocking with return status for already exists or abandoned.

WaitForSingleObject/WaitForMultipleObjects Calls blocked until current owner releases specified mutex object. Calls non-blocking while waiting for a mutex object it already owns.

ReleaseMutex Called once per call returned from Wait function. Abandoned state if not called before owner thread terminates.

CloseHandle Releases and Destroys mutex object upon last handle close.

3.Semaphores

CreateSemaphore Creates named or unnamed semaphore object if it doesn’t already exist.

WaitForSingleObject/WaitForMultipleObjects Calls blocked until semaphore count is non-zero. Semaphore count decreased when wait succeeds.

ReleaseSemaphore Increments semaphore count by specified amount.

CloseHandle Destroys a semaphore object upon closing its last handle.

4.Manual Events

Signaled with SetEvent. Kernel releases all waiting threads. Kernel releases all subsequently waiting threads. Must explicitly set to non-signaled with ResetEvent.

Signaled with PulseEvent. Kernel releases all waiting threads. Kernel automatically transitions event to non-signaled.

5.Autoreset Events

Signaled with SetEvent. Kernel releases a single waiting thread. Other waiting threads remain blocked. Kernel automatically transitions event to non-signaled. Event remains signaled until a single thread is released.

Signaled with PulseEvent. Kernel releases at most one waiting thread. Kernel automatically transitions event to non-signaled. Even if no thread has been released.

6.Interlocked Functions

解决对资源的原子访问问题。

The interlocked functions allow a thread to safely perform a read/modify/write sequence on 32 bit aligned shared data without disabling interrupts or incurring the overhead of a kernel call. The interlocked functions are the most efficient mechanism for safely performing this type of access. The kernel implements this functionality by restarting the function call if it is interrupted by an interrupt or data abort before completing.

InterlockedIncrement Increment a shared variable and check resulting value.

InterlockedDecrement Decrement shared variable and check resulting value.

InterlockedExchange Exchange values of specified variables.

InterlockedTestExchange Exchange values when a variable matches.

InterlockedCompareExchange Atomic exchange based on compare.

InterlockedCompareExchangePointer Exchange values on atomic compare.

InterlockedExchangePointer Atomic exchange of a pair of values.

InterlockedExchangeAdd Atomic increment of an Addend variable.

下一篇将涉及到内存构架方面知识。