阅读:1261回复:2
C++ in the kernel
CompuwareCorporation
C++ in the kernel Whether to use C++ or C in the Windows kernel environment is the topic of a long-standing debate in the driver development community. (For example, see the newsgroup: microsoft.public.win32.programmer.kernel.) On one side are developers claiming that inherent characteristics of C++ make it unsuitable for kernel driver programming. Indeed, most drivers today are written in C, and C is what the DDK recommends. On the other side are developers who find that the design power and strong type checking of C++ provide for more robust and maintainable drivers. Let’s consider the claims. C++ myths versus reality 1. The Windows kernel has no runtime support for C++. While this claim is true, adding a basic C++ runtime support to a kernel-mode driver is straightforward. 2. C++ causes hidden overhead that is unacceptable for kernel driver programming. Proponents of this claim point out that innocent-looking statements ( e.g., a = b) can result in the invocation of copy constructors and trigger a chain of operations, allocations, etc. This claim is typical of a C programmer who has become used to mapping C statements to CPU instructions to assess the efficiency of the code. Admittedly, the higher level of abstraction in C++ does require careful programming, coupled with an understanding of the potential “cost” of each statement. This is one rule of thumb for using C++ in the kernel. Sloppy programming in C++ might cost you dearly. A related caveat is that a given piece of C++ source code tends to call many more small functions/methods than a similarly sized piece of C source code. Fortunately, those calls can be optimized. You can apply the inline keyword (with discretion, of course) to optimize out those small method calls for the release build. 3. C++ requires more memory, particularly for the stack. C++ allows a program to easily instantiate objects on the stack and pass objects as parameters into methods. Hence, the stack might grow wildly, which could certainly cause problems with the limited kernel stack (the Windows 2000 stack is around 8K bytes). The response to this concern is similar to the response above: When using C++, you’d better know what you’re doing. Passing objects by value―for non-trivial types―should be avoided in the kernel. (Use references for formal parameters when defining method signatures.) For more deterministic behavior, avoid relying on the compiler to generate default constructors and copy constructors. You should explicitly define or disable those operators (e.g. by declaring them private). 4. C++ exceptions are not supported. Standard C++ exception handling (try / catch / throw) is not supported by the runtime libraries to which kernel-mode drivers link. This is not to say that C++ exceptions can’t be implemented in the kernel. But programming with C++ exceptions is a tricky art, not well suited for the driver environment. Fortunately, Microsoft C++ does not enforce the use of exceptions. However, the Windows kernel makes extensive use of Microsoft’s proprietary structure exception handling (SEH). SEH is available for drivers written in C using keywords _try and _except. Logically, SEH yields behavior similar to that of the standard exception handling. The caveat for C++ programmers is that SEH is a C mechanism. That is, SEH does not call destructors when unwinding the stack on an exception. 5. Run Time Type Identification (RTTI) is a killer. RTTI adds the ability to query the type of an object at runtime. This is sometimes used in designs with multiple levels of inheritance by forcing the compiler/linker to include extra class information into the executable module―hence, the overhead. In the kernel, RTTI is not supported. Frankly, it’s not apparent that there is any good reason to use it in drivers. (RTTI is optional with Microsoft C++.) 6. Virtual functions are evil. The most prominent premise of C++ is polymorphism, which is commonly associated with the use of virtual functions. Virtual functions are described as “performance killers” because they require (1) extra memory for vtable placement and (2) extra instructions for vtable lookup for each call into a virtual method. This is all true, so a good class designer should use discretion when defining a base class interface. Only those methods for which it makes sense to override should be declared as such. The length and projected frequency of the method’s invocation also should be considered. For example, a 200-line, sporadically called method should not affect program performance, whether it is defined as virtual or not. Meanwhile, a frequently called virtual “two-liner” should be scrutinized as a possible performance problem. This is a classic tradeoff between extensibility and overhead. C++ templates offer an alternative form of code reuse. Template specializations provide a “static” form of polymorphism, which might be a good choice for performance-sensitive implementations. 7. C++ means frameworks, and frameworks are evil. The kernel-mode C API is complicated enough; what’s the benefit to mastering another API that is C++-based? Besides, a poorly designed or a buggy framework can double the pain of writing and debugging a driver. 2 www.compuware.com 3/02 Compuware products and professional services― delivering quality applications Compuware is a leading global provider of software products and professional services which IT organizations use to develop, integrate, test and manage the performance of the applications that drive their businesses. Our software products help optimize every step in the application life cycle―from defining requirements to supporting production service levels―for web, distributed and mainframe platforms. Our services professionals work at customer sites around the world, sharing their real-world perspective and experience to deliver an integrated, reliable solution. Please contact us to learn more about how our comprehensive products and services can help your organization improve productivity, create higher quality applications and ensure performance in production. All Compuware products and services listed within are trademarks or registered trademarks of Compuware Corporation. All other company or product names are trademarks of their respective owners. ? 2002 Compuware Corporation Developers are naturally cautious about using third-party frameworks for precisely the preceding reasons. A well-designed and tested framework, however, can significantly reduce development time. The framework can do this by encapsulating routine code and shrinking the complexity of the native, flat C API into a much smaller, coherent set of reusable C++ classes. 8. C++ means object-oriented, and OO is not suited for driver programming. Drivers run in the kernel’s event-driven environment, so they are best implemented as state machines using strictly procedural C programming. Doing so makes the drivers easier to test and debug. This argument is difficult to rebut, because the core issue is a matter of the coding style and development practices in a particular project team. C++ is not necessarily a good choice for all driver projects. However, the more complicated the project, the more it makes sense to apply OO coding techniques. In addition, it is quite common in the driver community to use C++ as a “better C.” This allows the developer to preserve the conventional driver programming style and take advantage of the strong type checking and syntax conveniences of C++. 9. C++ is less portable than C. The truth is that the strict type checking of C++ is a major advantage in producing portable code. For example, see “Moving Up to 64 Bits,” Arch D. Robinson, DDJ #321, February 2001, for the benefits of using C++ in porting from a 32-bit to a 64-bit platform. Another advantage C++ provides is encapsulation, which allows the developer to hide platform differences behind C++ wrappers. This promotes the “single source/multiple platform paradigm” (“platform” here means different versions of the Windows OS). 10. Some powerful C++ libraries, such as STL, cannot be used in the kernel. The reasons most frequently given for this are that STL relies on exceptions, which we’ve already said are not very usable in the kernel, and that STL tends to use dynamic allocations, which results in unexpected overhead and unpredictable performance. However, there are STL implementations that can be customized for specific compiler and runtime environments. For example, Compuware’s DriverStudio? comes with a version of STL that has been customized for use in the Windows kernel. This version of STL was adopted from the SGI distribution at http://www.sgi.com/tech/stl. It’s unlikely that the C++ versus C debate will result in a victory on either side. Experiments with Microsoft C++ 6.0 and the XP DDK compiler show that C++ can be used to write well-performing kernel-mode drivers, in spite of the compiler’s numerous issues with C++ standard support. However, it’s up to the developer to choose the language with which he or she is comfortable. |
|
|
沙发#
发布于:2004-08-19 16:54
你E文好,有时间翻译一下? :D :D
我觉得,如果C++够牛,对kernel理解的也够牛,是可以用C++来写驱动,甚至能写个standard Driver lib,像DriverWorks一样去卖¥ :D,不过这绝对是个巨大的工作,比写多少个Driver还难 :D 简单点的像“C with Class”的C++写法,也能用用,恐怕收益不大 |
|
板凳#
发布于:2004-08-19 21:02
你E文好,有时间翻译一下? :D :D |
|