内核模式驱动不推荐使用C++的缘由

原创 2013年12月03日 13:36:40
本文所讲内容主要源自Windows DDK文档。

一、内存页面交换
和用户模式程序不同,内存页面交换对内核模式的代码不是透明的,而是需要一定程度的主动管理,要保证在代码执行过程中不会需要载入新的页面。编译器有相关的扩展#pragma指令来帮助C代码显式控制生成的二进制代码布局,以便相关的代码被放在一起,被调用时只需载入最少的页面。

而对C++而言,还存在一些编译器自动生成的代码块和数据,没有办法主动控制它们。比如编译器生成的缺省构造函数、析构函数、类型转换函数、赋值运算符重载;用于支持多重继承的adjustor thunk(没听说过?读这个),用于实现虚函数调用的virtual function thunk,用于管理基类和多态的virtual function table thunk;自动实例化(非显式实例化)的泛型代码;还有虚表本身。

对于这些问题,大多可以通过避免使用这些C++语言特性来解决。

此外,内联函数本身,也可能导致问题。因为,它有可能没被内联,而是生成了一个普通的函数,而且取决于被调用的位置,它可能存在于多个代码段。这个可以用宏或者编译器扩展的__forceinline来替代。

二、堆分配
对普通应用而言,通常我们只用一个动态内存分配的堆。而在内核模式驱动中,是很可能会用到多个内存池的,至少你会用到tagged memory。tagged memory其实就是给分配的内存加一个数字标签,以方便调试诊断,快速找到是谁的代码出的问题。这都意味着,对动态内存的分配和释放,需要一些额外的参数。这对C风格的分配函数,加个参数是很容易的,而对C++的new/delete,则很难办。new算符其实是可以带一个指针参数的,但delete算符没有。

三、STL
内核模式能使用的运行时库并不是全部,而只是一个子集,有些链接时报错,有些能链接但不起作用,也有的看起来能用但会产生某些副作用。STL大部分以源码形式存在于头文件里,看起来似乎没什么问题,但其实,它内部偶尔也会调用一些不能在内核模式使用的运行库函数。

STL对象也是不宜跨越DLL边界的。这个其实不只是STL,所有C++的对象都不宜,写过C++的DLL的应该都知道。C++的API是没有ABI规范的,不同编译器、不同版本、不同实现生成的二进制API接口都可能不一样,所以需要在外部接口上用extern "C",因为C是有ABI规范且被广泛支持的。即使如此,也还要注意,不同的DLL是可能用不同的堆的,所以对动态内存分配的资源,要遵循谁分配谁释放的原则。

此外,STL编译出的代码虽然效率很高,但代码体积一般都偏大,对驱动而言,一般期望其更精简一些。

所以,总体而言,官方并不推荐在内核级驱动里使用STL。

四、异常和RTTI
首先,内核模式的库并不是异常安全的,所以异常的使用必须独立于任何外部交互和库调用。其次,异常发生时的栈内存开销很大,对栈空间非常有限的内核模式程序而言,最多可以达到总栈空间的1/6。但是,编译器为C提供的结构化异常处理(__try/__except/__finally)没有这些问题,可以使用。

RTTI则依赖于一个在内核模式不能用的库,所以不能用。

总结
刨去这些东西之后,就得到一个大体可用的C++功能子集了。什么,还剩什么功能?很多呀,比如命名空间、引用类型、运算符重载……哎,别扔板砖啊。

驱动开发之用户模式和内核模式

运行 Windows 的计算机中的处理器有两个不同模式:“用户模式”和“内核模式”。根据处理器上运行的代码的类型,处理器在两个模式之间切换。应用程序在用户模式下运行,核心操作系统组件在内核模式下运行。...
  • liyun123gx
  • liyun123gx
  • 2014年06月09日 12:50
  • 894

Windows Driver Foundation - KMDF 内核模式驱动框架结构 全文下载

WDM的驱动很复杂,引起的蓝屏问题众多,于是微软为vista之后的操作系统提供了新的驱动开发框架Windows Driver Foundation 微软自己的介绍:https://www.mic...
  • cosmoslife
  • cosmoslife
  • 2012年06月18日 06:06
  • 748

Windows Driver Foundation - KMDF 内核模式驱动框架结构 第二部分

KMDF对象模型 KMDF定义了以对象为基础的编程模型,其中对象类型代表了常见的驱动结构。每个对象输出方法(功能)和属性(数据)给驱动访问,并且关联到对象指定的事件,驱动可以通过提供事件回调函数...
  • cosmoslife
  • cosmoslife
  • 2012年06月18日 06:07
  • 1715

C++应该使用异常吗

其实关于这点,很多人没有一个统一,google c++ code style 不推荐使用,连go语言里异常也不推荐使用。 根据我项目经验,使用异常会使代码整洁、不需要每个层都检查那么多的返回错误。 ...
  • lotusdeng2010
  • lotusdeng2010
  • 2013年02月25日 17:43
  • 1563

不推荐使用注解 @Deprecated

加上 @Deprecated 后 方法名称显示: 中划线(删除线) 意为: 发生这些变化并不会影响编译,只是提醒一下程序员,这个方法以后是要被删除的,最好别用。 ...
  • wide288
  • wide288
  • 2017年11月17日 20:19
  • 491

内核学习-中断级别,分页内存,用户模式以及内核模式

一、中断级别1.PASSIVE_LEVEL 代码运行在这个级别不用担心分页内存被交换出去。处在PASSIVE_LEVEL的地方为: 1.Driver_Entry,Unload,ShutDown,D...
  • haolipengzhanshen
  • haolipengzhanshen
  • 2015年10月08日 21:20
  • 871

为什么要使用智能指针

# include using namespace std; class U_Ptr {     friend class HasPtr;     int *ip;     size_t ...
  • a474711079
  • a474711079
  • 2014年05月19日 00:58
  • 414

Windows Driver Foundation - KMDF 内核模式驱动框架结构 第一部分

简介 内核模式驱动框架(KMDF)是开发内核模式驱动的基础框架。它提供C语言设备驱动接口(DDI),能用来创建Microsoft® Windows® 2000及以后版本的驱动。本质上,框架就是一...
  • cosmoslife
  • cosmoslife
  • 2012年06月18日 06:06
  • 891

使用回调函数实现类型c++的泛型算法

max 函数可以在任意一组对象中找出最大值,实现者并不知道怎样去比较两个对象的大小,调用者需要提供一个做比较操作的回调函数。 // generics.h #ifndef GENERICS_H #de...
  • tzshlyt
  • tzshlyt
  • 2016年11月01日 10:17
  • 409

linux的用户模式和内核模式

MS-DOS等操作系统在单一的CPU模式下运行,但是一些类Unix的操作系统则使用了双模式,可以有效地实现时间共享。在Linux机器上,CPU要么处于受信任的内核模式,要么处于受限制的用户模式。除了内...
  • sinat_15799399
  • sinat_15799399
  • 2015年03月13日 11:24
  • 1506
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:内核模式驱动不推荐使用C++的缘由
举报原因:
原因补充:

(最多只允许输入30个字)