********************************LoongEmbedded********************************

作者:LoongEmbedded(kandi)

时间:2011.10.04

类别:WINCE驱动开发

********************************LoongEmbedded********************************

微软总结了WINCE开发更安全可靠设备驱动的最佳实践,如下所示:

1.  根据需要使用异常处理结构(SEH)来处理异常,_try/_except模型就是我们熟知的C++的SHE处理模型,下面根据WAV_IOControl()来进一步学习这SHE处理机制。_except关键字后面跟着是一个各种类型的表达式,在一个函数中,可以有多个_try/_except语句,它们可以是一个平面的线性结构,可以是分层的嵌套结构,也可以是这两种结构的混合使用。

图1

上图的代码的执行流程如下:

1)  受监控的代码先被执行。

2)  如果受监控代码在执行过程中,没有出现异常,那么控制流将转入到_except定义的异常处理代码模块的后面执行,也就是直接返回FALSE。

3)  如果受监控代码出现执行异常,那么控制流将进入到_except后面的表达式中,也即首先计算这个表达式的指,然后再根据这个值来做出相应的处理。

下面来描述这个表达式中的相关知识。

1)  GetExceptionCode()

GetExceptionCode()函数用于获取已经发生的异常的类型,该函数只能在筛选表达式(filter expression)或者try-except异常处理的异常处理阻塞(exception-handler block)中调用,它的返回值是下面的值:

EXCEPTION_ACCESS_VIOLATION

调用该函数的程序尝试访问一个它没有合适权限访问的虚拟地址产生的异常。

EXCEPTION_ARRAY_BOUNDS_EXCEEDED

调用该函数的程序尝试访问一个越界的数组元素,而且底层硬件支持越界检查的情况下引发的异常。

EXCEPTION_BREAKPOINT

触发断点时引发的异常。

EXCEPTION_DATATYPE_MISALIGNMENT

程序尝试读或者写未经对齐的数据时产生的异常。

EXCEPTION_FLT_DENORMAL_OPERAND

如果浮点数运算中的操作数的值太小,以致无法采用标准的浮点数表示时产生的异常。

EXCEPTION_FLT_DIVIDE_BY_ZERO

程序尝试对浮点数除法的除数是0进行运算时产生的异常。

EXCEPTION_FLT_INEXACT_RESULT

浮点运算的结果不能精确表示成小数时产生的异常。

EXCEPTION_FLT_INVALID_OPERATION

此异常表示不包含在这些列举中的浮点数异常。

EXCEPTION_FLT_OVERFLOW

浮点运算的指数超过所能表示的最大值引发的异常。

EXCEPTION_FLT_STACK_CHECK

浮点运算发生栈上溢或者下溢时引发的异常。

EXCEPTION_FLT_UNDERFLOW

浮点运算的指数超过所能表示的最小值引发的异常。

EXCEPTION_INT_DIVIDE_BY_ZERO

整数除法的除数是0时引发的异常。

EXCEPTION_INT_OVERFLOW

整数操作的结果溢出时引发的异常。

EXCEPTION_NONCONTINUABLE_EXCEPTION

发生一个不可继续执行的异常时,如果程序继续执行,则会引发此异常。

EXCEPTION_PRIV_INSTRUCTION

程序尝试去执行一条当前CPU模式不支持的指令时引发该异常。

EXCEPTION_SINGLE_STEP

单步调试时,每个陷阱追踪或单条指令执行时引发该异常。

要调用GetExceptionCode()函数,需要把excpt.h头文件包含进来,其中上面代码提到的STATUS_ACCESS_VIOLATION=EXCEPTION_ACCESS_VIOLATION,这在winbase.h中使用宏定义做了等同的定义。

2)  Excpt.h对异常处理except()中的合法的值定义如下

#define EXCEPTION_EXECUTE_HANDLER        1

表示系统识别到此异常,并且转移控制到异常处理代码部分继续执行。

#define EXCEPTION_CONTINUE_SEARCH        0

当前的_except模块不是该异常所对应的正确的异常处理模块,系统将继续查找合适的异常处理模块来处理该异常。

#define EXCEPTION_CONTINUE_EXECUTION    -1

系统停止查找异常处理并且返回到发生异常的控制流所在的地方,继续执行,但是,如果这个异常是一个不可继续执行的异常时,那么将引发一个EXCEPTION_NONCONTINUABLE_EXCEPTION

的异常。

异常分为系统异常和软件异常,上面列举的就是系统异常,而软件异常通过RaiseException()函数抛出。

3)  RaiseException()

在调用的thread中可以通过调用该函数来引发一个异常,该函数的声明如下:

VOID WINAPI RaiseException(

DWORD dwExceptionCode,

DWORD dwExceptionFlags,

DWORD nNumberOfArguments,

CONST DWORD *lpArguments

);

下面描述参数及其功能

dwExceptionCode

一个在引发异常时应用程序定义的异常代码,筛选表达式(也即_except()中的表达式)和异常处理程序的异常处理阻塞可以调用GetExceptionCode()函数来获得异常代码。需要注意的一点是,系统会在显示信息之前清除dwExceptionCode参数的第28位,该位是一个系统保留的异常位,仅供系统自身使用。比如以一个异常代码0xFFFFFFFF调用RaiseException()函数的时候,系统会以异常代码0xEFFFFFFF显示。

dwExceptionFlags

异常标志,这可以赋值为零,表示一个可持续异常,或者使用EXCEPTION_NONCONTINUABLE标志来表示一个不可持续的异常。发生不可持续的异常后,任何企图继续执行的行为将导致触EXCEPTION_NONCONTINUABLE_EXCEPTION异常。

lpArguments

nNumberOfArguments

表示lpArguments参数数组中的参数个数,这个值不能超过EXCEPTION_MAXIMUM_PARAMETERS;   如果lpArguments为NULL ,则忽略此参数。

lpArguments

指向32位参数的数组的长指针,这个参数可以是NULL,这些参数可以包含任何应用程序所定义的数据,而这些数据需要传递给异常处理程序的筛选表达式。那么在筛选表达式可以调用GetExceptionInformation()函数来获取应用程序传递过来的数据。

一个进程可以通过调用RaiseException()函数并且使用异常处理结构来处理私有的,软件引起的或者应用程序定义的异常。下面列出在引发一个异常的时候,调度程序如何查找合适的异常处理程序来处理此异常的步骤:

⑴如果有调试器,系统将尝试通知进程的调试器。

⑵如果这一进程没有被调试,或者相关的调试器没有处理这个异常,系统将尝试通过查找引发异常的线程的堆栈帧的来定位一个基于帧的异常处理程序。系统首先查找当前的堆栈帧,然后继续查找先前的堆栈帧。

⑶如果没有找到基于帧的异常处理程序,或者基于帧的异常处理程序处理该异常,系统将会第二次尝试通知进程的调试器。

⑷如果该进程仍未被调试,或者相关的调试器不能处理该异常,系统根据异常的类型来提供默认的程序,对于大多数异常,默认的动作就是调用ExitProcess函数来退出进程。

2.  在IOCTL调用中检查对嵌套指针(nested pointers)的访问权限(access permissions)。

3.  在非流式接口的入口函数,比如GWES的键盘函数的入口函数中检查对嵌套指针的访问权限。

4.  使用ceddk.dll的函数来访问硬件,不要使用wdm.h中的宏定义,这不仅有利于标准化,更便于移植。

5.  检查任何函数调用的返回值,这样可以识别调用失败或者返回意料之外的结果,以便我们做更合理的处理。

6.  使用DEBUGCHK宏或者相关的宏来检查一些假设(assumptions),但要相应地处理发生的错误情况。

DEBUGCHK宏维护(assert)一个表达式,如果此表达式为FALSE,则会调用DebugBreak函数,DebugBreak函数使当前的进程引起一个断点异常,这样调用的线程可以通知调试器并且强迫它采取行动。但如果调用DebugBreak函数的线程没有附属的调试器,那么DebugBreak函数将被忽略,并且如果没有其他的异常或者调用DebugBreak函数时,这个线程将继续执行。DEBUGCHK宏的用法举例如下:

DEBUGCHK(dwCurrentNumberOfItems < dwMaxNumberOfItems);

如果dwCurrentNumberOfItems大于或者等于dwMaxNumberOfItems,那么对于debug版本的系统来说,将会输出下面的信息

MyProgram: DEBUGCHK failed in file C:\WINCE500\Programs\MyProgram\.\main.c at line 31

也即debug消息会把出错的文件名和行数打印出来。

7.  当一个内部线程访问一个外部提供的buffer的时候,使用CeAllocAsynchronousBuffer函数和SHE,这样可以把调用者的buffer排列(marshals)到内核的虚拟内存中。在WINCE6.0中,不需要改变线程的权限来访问外部提供的buffer。

8.  证实访问设备驱动并且被设备驱动信赖的任何应用程序(Verify that any applications that call into a device driver are trusted)。

9.  检查正在调用的应用程序的信任值,这个信任值通过调用CeGetCallerTrust函数来获得。接着,如果必要的话,Flags的值为DEVFLAGS_TRUSTEDCALLERONLY(0x00010000的)驱动有权强迫只被受信任的调用者的使用,也就是说带有此标志值的驱动只被它信任的应用程序打开,这是相对于WINCE5.0及之前版本的操作系统的概念,对于WINCE6.0之后的就有些不一样了。

10. 使用C/C++的代码分析(code analysis)来编程,这部分祥看帮助文档。

WINCE开发更安全可靠设备驱动的最佳实践相关推荐

  1. .NET、C#与Silverlight开发圣典——分享15位MVP的最佳实践经验

    <.NET.C#与Silverlight开发圣典--分享15位MVP的最佳实践经验> 基本信息 原书名:Real World .NET 4, C#, and Silverlight:lnd ...

  2. Linux驱动开发--写一个块设备驱动

    原文地址:[原创] 写一个块设备驱动 http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=2017377&fromuid=288 ...

  3. Linux 驱动开发 三:字符设备驱动框架

    一.参考 (3条消息) Linux 字符设备驱动结构(一)-- cdev 结构体.设备号相关知识解析_知秋一叶-CSDN博客 (3条消息) linux设备驱动框架_不忘初心-CSDN博客_linux设 ...

  4. linux驱动开发5之字符设备驱动新接口

    1.新接口与老接口 1)老接口:register_chrdev static inline int register_chrdev(unsigned int major, const char *na ...

  5. 迅为IMX6ULL开发板Linux I2C设备驱动编写流程-信息描述

    1 .不使用设备树文件 当开始编写 I2C 设备驱动时,首先要添加设备信息.先来看一下在不使用设备树,使用平台文件时, 如何在平台文件中添加 I2C 设备信息. 在平台文件中通过 i2c_board_ ...

  6. Linux字符设备驱动程序开发(1)-使用字符设备驱动

    1.编译/安装驱动 在Linux系统中,驱动程序通常采用内核模块的程序结构来进行编码.因此,编译/安装一个驱动程序,其实质就是编译/安装一个内核模块.把下面的范例代码拷贝到Linux系统中: memd ...

  7. 软件开发的三大关键安全趋势和最佳实践

     聚焦源代码安全,网罗国内外最新资讯! 编译:代码卫士 专栏·供应链安全 数字化时代,软件无处不在.软件如同社会中的"虚拟人",已经成为支撑社会正常运转的最基本元素之一,软件的安全 ...

  8. Web开发人员的10个数据库优化最佳实践

    新钛云服已累计为您分享663篇技术干货 数据库优化已经成为web开发人员提高web应用程序性能,从而改善用户体验的关键.对一些人来说,这可能听起来不太吸引人,但好处是值得的.如果正确地优化数据库,就可 ...

  9. 【Unity3D游戏开发】之游戏目录结构之最佳实践和优化 (十一)

    游戏目录结构之最佳实践 前置条件 1.多人协作开发,git管理 2.游戏不大,所有Scene合并到一起Scene中,eg.RoleScene.MapScene.StoreScene 3.Master一 ...

最新文章

  1. 语义分割:基于openCV和深度学习(一)
  2. lnmp架构——nginx的负载均衡
  3. SylixOS iMX6平台I2C总线驱动
  4. C++ const与define
  5. python读取excelsheet-python读取excel文件中所有sheet表格
  6. ABAP算法:找出递归的物料
  7. rocketmq 顺序消费_RocketMQ核心概念扫盲
  8. python 安装talib包
  9. U盘安装Ubuntu操作系统
  10. 裤子尺码对照表eur40_裤子尺码对照表
  11. 叶卡捷琳娜与狄德罗的故事
  12. Excel绘制排名变化曲线图(折线图),附源文件
  13. 关系网络lbs的应用_冒泡网王江:熟人关系将成LBS最重要商业模式
  14. 利用栈实现精制转换c++
  15. nginx禁止某些指定的浏览器标识来爬我们网站
  16. 服务器Linux硬盘分区,Linux磁盘分区实现原理及方法解析
  17. 极客爱情 2.2 | 程序员是这样撩妹的
  18. 轻轻松松做演讲的小窍门
  19. 神探夏洛克 | 不再卖腐,第四季的最大的看点变成了……
  20. Java毕设项目高校智慧校园学生系统(java+VUE+Mybatis+Maven+Mysql)

热门文章

  1. java里的局部变量为什么不能加static?
  2. 074_JSON.stringify()
  3. 096_JavaScript事件
  4. Java解码vhd的磁盘文件,VHD Java library
  5. java 实现二叉树操作
  6. 计算机网络期中考试总结反思,期中考试总结反思作文(通用6篇)
  7. matlab中 三种方法计算 Ax b,在MATLAB中,方程Ax=B的解可以用哪个命令求得? matlab 求助 解方程组...
  8. php 检测密码,php检测密码强度
  9. Java高并发编程(三):Java内存模型
  10. 计算机网络期中考察方案,计算机网络期中考试题 b卷_ans.docx