继续阅读How to successfully build packages for WD My Cloud from source
How to successfully build packages for WD My Cloud from source
继续阅读How to successfully build packages for WD My Cloud from source
Windows下的下载工具--迅雷,之所以下载速度快,乃是它能搜索资源、为己所用,而不是仅仅从原始地址这单一资源处下载。
Ubuntu下也有类似的工具,那就是aira2。
aira2是一个命令行下载工具,可以配合其他图形界面的下载软件使用。我用的是uget+aria2。uget本身是一个小巧实用的多线程下载工具,加上aria2作为插件,下载速度有明显提高。
一、安装。
uget和aria2都可以在“软件中心”中安装。但是版本都是比较旧的版本。
如果需要安装最新的版本,可以在终端中添加ppa进行安装:
1.uget的安装:
1 2 3 |
sudo add-apt-repository ppa:plushuang-tw/uget-stable sudo apt-get update sudo apt-get install uget |
2.aria2的安装:
1 2 3 |
sudo add-apt-repository ppa:t-tujikawa/ppa sudo apt-get update sudo apt-get install aria2 |
安装完aria2后,可以在终端中运行aria2 -v,查看版本和支持的特性。需要1.10以上的版本才能支持资源搜索。
二、使用与设置技巧
1.主界面及版本
2.启用aria2插件
3.设置下载任务的属性(同时下载几个任务、多少个服务器、保存位置等)
服务器数设置为16比较合适。
参考网址 http://blog.csdn.net/luojiming1990/article/details/9078447
写python脚本的时候发现这样一个问题:从xls文件导出到txt时,无法直接转换为int型数据,输出查看发现和文件编码方式产生的附加信息有关用一个简单的文件举例
1 2 3 4 5 6 7 8 9 10 |
90905 90907 90908 90909 90939 90940 90946 90959 90961 90965 |
当文件分别用ascii,utf8,utf8+bom作为编码格式时,显示输出结果如下:
使用ascii编码的输出:
1 |
['90905\r\n', '90907\r\n', '90908\r\n', '90909\r\n', '90939\r\n', '90940\r\n', '90946\r\n', '90959\r\n', '90961\r\n', '90965'] |
使用utf8编码的输出:
1 |
['90905\r\n', '90907\r\n', '90908\r\n', '90909\r\n', '90939\r\n', '90940\r\n', '90946\r\n', '90959\r\n', '90961\r\n', '90965'] |
使用bom编码的输出:
1 |
['\xef\xbb\xbf90905\r\n', '90907\r\n', '90908\r\n', '90909\r\n', '90939\r\n', '90940\r\n', '90946\r\n', '90959\r\n', '90961\r\n', '90965'] |
原来utf8+bom不能直接转换int的原因在这里,它在文件头插入了一个表示文件编码的信息\xef\xbb\xbf,那么UTF-8(无BOM)和UTF-8这两个有什么区别呢?BOM是什么呢?
UTF-8 BOM又叫UTF-8 签名,其实UTF-8 的BOM对UFT-8没有作用,是为了支持UTF-16,UTF-32才加上的
BOM,BOM签名的意思就是告诉编辑器当前文件采用何种编码,方便编辑器识别,但是BOM虽然在编辑器中不显示,但是会产生输出,就像多了一个空行。
Byte Order Marks are special characters at the beginning of a Unicode file to indicate whether it is big or little endian, in other words does the high or low order byte come first. These codes also tell whether the encoding is 8, 16 or 32 bit. You can recognise Unicode files by their starting byte order marks, and by the way Unicode-16 files are half zeroes and Unicode-32 files are three-quarters zeros. Unicode Endian Markers
Byte-order mark Description
EF BB BF UTF-8
FF FE UTF-16 aka UCS-2, little endian
FE FF UTF-16 aka UCS-2, big endian
00 00 FF FE UTF-32 aka UCS-4, little endian.
00 00 FE FF UTF-32 aka UCS-4, big-endian.
UTF- 8以字节为编码单元,没有字节序的问题。UTF-16以两个字节为编码单元,在解释一个UTF-16文本前,首先要弄清楚每个编码单元的字节序。例如收到 一个“奎”的Unicode编码是594E,“乙”的Unicode编码是4E59。如果我们收到UTF-16字节流“594E”,那么这是“奎”还是 “乙”?
Unicode规范中推荐的标记字节顺序的方法是BOM。BOM不是“Bill Of Material”的BOM表,而是Byte Order Mark。BOM是一个有点小聪明的想法:
在 UCS编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输 字符"ZERO WIDTH NO-BREAK SPACE"。
这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。
UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB BF。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。
Windows就是使用BOM来标记文本文件的编码方式的。
原来BOM是在文件的开始加了几个字节作为标记。有了这个标记,一些协议和系统才能识别。
ok,说了这么多背景,那么如何解决这个问题呢?
对UTF-16, Python将BOM解码为空字串。然而对UTF-8, BOM被解码为一个字符,如例:
1 2 3 |
>>> codecs.BOM_UTF16.decode( "utf16" ) >>> codecs.BOM_UTF8.decode( "utf8" ) u'\ufeff' |
简单的做法是在文件读入时使用
1 2 3 |
import codecs f = codecs.open(sys.argv[1],'r', 'utf_8_sig') |
即可,具体可以参见[http://docs.python.org/library/codecs.html#module-encodings.utf_8_sig|http://docs.python.org/library/codecs.html#module-encodings.utf_8_sig]
或者:
1 |
u.lstrip( unicode( codecs.BOM_UTF8, "utf8" ) ) |
1 2 3 4 5 6 7 8 |
out = file( "someFile", "w" ) out.write( codecs.BOM_UTF8 ) out.write( unicodeString.encode( "utf-8" ) ) out.close() out = file( "someFile", "w" ) out.write( codecs.BOM_UTF8 ) out.write( unicodeString.encode( "utf-8" ) ) out.close() |
参考 http://www.cnblogs.com/DDark/archive/2011/11/28/2266085.html
在处理字符串时,常常会遇到不知道字符串是何种编码,如果不知道字符串的编码就不能将字符串转换成需要的编码。面对多种不同编码的输入方式,是否会有一种有效的编码方式?chardet是一个非常优秀的编码识别模块。
1 2 3 4 5 6 7 8 9 |
import chardet import urllib #可根据需要,选择不同的数据 TestData = urllib.urlopen('http://www.baidu.com/').read() print chardet.detect(TestData) 运行结果: {'confidence': 0.99, 'encoding': 'GB2312'} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import urllib from chardet.universaldetector import UniversalDetector usock = urllib.urlopen('http://www.baidu.com/') #创建一个检测对象 detector = UniversalDetector() for line in usock.readlines(): #分块进行测试,直到达到阈值 detector.feed(line) if detector.done: break #关闭检测对象 detector.close() usock.close() #输出检测结果 print detector.result 运行结果: {'confidence': 0.99, 'encoding': 'GB2312'} |
应用背景,如果要对一个大文件进行编码识别,使用这种高级的方法,可以只读一部,去判别编码方式从而提高检测速度。
做python开发,要用到第三方包,关于MAC下面如何安装Pip ,可以参考前面的 Mac OS 10.9 下python安装easy_install pip 现在我们看看在Windows下面的操作,打开 Pip的官方安装指南https://pip.pypa.io/en/latest/installing.html
pip works with CPython versions 2.6, 2.7, 3.1, 3.2, 3.3, 3.4 and also pypy.
pip works on Unix/Linux, OS X, and Windows.
Note
Python 2.5 was supported through v1.3.1, and Python 2.4 was supported through v1.1.
To install or upgrade pip, securely download get-pip.py.(如果官网下载不下来,可以点这个链接在本网站下载)
Then run the following (which may require administrator access):
1 |
python get-pip.py |
If setuptools (or distribute) is not already installed, get-pip.py will install setuptools for you. [2]
To upgrade an existing setuptools (or distribute), run pip install -U setuptools. [3]
To enable the use of pip from the command line, ensure the Scripts subdirectory of your Python installation is available on the system PATH. (This is not done automatically.)
Additionally, get-pip.py supports using the pip install options and the general options. Below are some examples:
Install from local copies of pip and setuptools:
1 |
python get-pip.py --no-index --find-links=/local/copies |
Install to the user site [4]:
1 |
python get-pip.py --user |
Install behind a proxy:
1 |
python get-pip.py --proxy="[user:passwd@]proxy.server:port" |
On Linux, pip will generally be available for the system install of python using the system package manager, although often the latest version will be unavailable.
On Debian and Ubuntu:
1 |
sudo apt-get install python-pip |
On Fedora:
1 |
sudo yum install python-pip |
由于工作上需要,把软件移植到英文版的os上(软件已是unicode版本的),发现RicheditCtrl
控件上显示的字体(本来内容应该显示为中文)乱码了。
发生乱码的具体代码:
1 2 3 |
mRichEditCtrl.SetSel(-1, -1); mRichEditCtrl.ReplaceSel( (LPCTSTR)Message.GetBuffer()); Message.ReleaseBuffer(); |
查找原因:可能是控件不了解字符串已经是unicode代码,所以控件根据locale 的code page来硬性将代码转换为unicode显示,所以出现乱码。
解决方法:
1 2 3 4 5 6 7 8 9 10 11 |
mRichEditCtrl.SetSel(-1, -1); #if UNICODE SETTEXTEX SetTxtEx = {0,}; SetTxtEx.flags = ST_SELECTION; SetTxtEx.codepage = 1200; BOOL bRet = ::SendMessage(mRichEditCtrl.GetSafeHwnd(), EM_SETTEXTEX, (WPARAM)&SetTxtEx, (LPARAM)Message.GetBuffer()); ASSERT(bRet); #else mRichEditCtrl.ReplaceSel( (LPCTSTR)Message.GetBuffer()); #endif Message.ReleaseBuffer(); |
一、下载与安装Nexus
想为Maven搭建私服,我们可以选择使用Nexus工具,目前已知提供war包的版本为2.2.0,其下载地址为:http://www.sonatype.org/nexus/go
这里我们下载War包,直接部署到Tomcat 7 下面,Ubuntu 下面是 /var/lib/tomcat7/webapps。
接下来我们可以在浏览器中输入http://127.0.0.1:8080/nexus/查看Nexus是否成功.
如果提示错误,则到 /var/log/tomcat7/localhost.YYYY-MM-DD.log 下面查看日志,有可能报告 /usr/share/tomcat7/sonatype-work 权限问题,则说明Nexus 没有权限创建这个目录,因此我们需要手工创建这个目录,然后赋予这个目录 777权限,然后重启 Tomcat.
目前最新的版本Nexus 2.12.0-01,(Nexus OSS官网下载2.x的Tomcat/WAR版本) 。3.x版本已经不提供WAR包下载了,只能是使用Jetty的版本了。
Ubuntu下面的操作如下:
1 2 3 4 5 6 7 8 9 |
$ cd ~ $ wget https://sonatype-download.global.ssl.fastly.net/nexus/oss/nexus-2.12.0-01-bundle.tar.gz $ sudo mkdir /var/opt/nexus-2.12.0-01 $ sudo tar -zxvf nexus-latest-bundle.tar.gz -C /var/opt/nexus-2.12.0-01 $ sudo ln -s /var/opt/nexus-2.12.0-01/nexus-2.12.0-01/ /var/opt/nexus |
修改bin/jsw/conf/wrapper.conf
,设置wrapper.java.command=jdk所在目录/bin/java
。
1 2 3 4 |
$ whereis java java: /usr/bin/java /usr/share/java /usr/share/man/man1/java.1.gz $ sudo vim /var/opt/nexus/bin/jsw/conf/wrapper.conf |
修改后的内容如下:
1 2 3 |
.......... wrapper.java.command=/usr/bin/java .......... |
设置目录的权限
1 2 3 4 5 6 7 8 9 |
$ chmod -R 777 /var/opt/nexus-2.12.0-01/sonatype-work $ chmod -R 777 /var/opt/nexus/logs $ chmod -R 777 /var/opt/nexus/tmp $ chmod -R 777 /var/opt/nexus/bin/jsw/linux-x86-64 $ chmod -R 777 /var/opt/nexus/bin/jsw/linux-x86-32 |
启动服务
1 2 3 4 |
$ /var/opt/nexus/bin/nexus start Starting Nexus OSS... Started Nexus OSS. |
这种安装模式下,访问的链接地址为http://localhost:8081/nexus
注意,首次启动的耗时时间很长,貌似需要建立数据库等,需要耐心等待几分钟。
如果成功,则出现下面的界面
通过上图我们可以发现我们已经成功的启动了Nexus,那么接下来要做的事情就更有意思了,在后续章节中笔者会陆续讲到应该如何使用Nexus工具来配置和管理咱们的私服仓库。
二、仓库类型
在上一章节中,笔者讲解了如何下载与安装Nexus工具。那么本章节咱么来看看如何使用Nexus工具配置和管理私服仓库。当然在使用Nexus之前你是需要登录的,缺省账号密码为:
account:admin;
password:admin123;
当成功登录后,你可以单击 Repositories属性看到如下页面:
由于admin这个账号是属于Administrator权限的,你也可以通过单击Security属性进行账户的配置:
Nexus的仓库类型一共有4种,每一种仓库类型均对应有不同的操作方式:
1、group: 仓库组;
2、hosted:宿主;
3、proxy:代理;
4、virtual:虚拟;
来吧,咱们先谈谈仓库组这个概念,一个仓库组类似一个仓库集合,它和仓库之间是一对多的关系,也就是说一个仓库组可以允许包含多个仓库,Nexus仓库用例图如下:
在咱们弄明白仓库组的作用后,咱们接着来看宿主仓库是干什么的。其实所谓宿主仓库可以理解为自定义仓库,用于存放一些在中央仓库无法下载的构件,比如自定义构件(你可以手动将自定义构件上传至hosted中)。
代理仓库起到的作用是代理作用,假设本地仓库向私服进行请求时,首先会去私服仓库的本地路径中寻找构件,如果没有找到则会从中央仓库进行下载。
虚拟仓库省略...
三、使用Nexus管理私服仓库
在了解Nexus的4种仓库类型后,咱们接下来要做的事情就是使用Nexus工具来管理咱们的私服仓库。先来看看Nexus为我们提供的一些缺省仓库:
从上图我们可以看出Nexus缺省为我们定义了1个仓库组,7个仓库。当中最主要的几个仓库为:
3rd party(宿主仓库):用于存放一些在中央仓库无法下载的构件仓库;
Apache Snapshots(代理仓库):代理ApacheMaven仓库快照版本的构件仓库;
Central(代理仓库):代理Maven中央仓库中发布版本构件的仓库;
当然你可以根据项目需要新建仓库组及仓库,但在建立这些私有的仓库之前,咱们还是先来看看如何使用Nexus为咱们提供的缺省构件仓库(其实很多时候你真没必要去新建仓库)。
选择Public Repositories分组,单击configuration选项,你可以为仓库组添加对应的仓库:
单击Save按钮保存即可配置完成。这里有一点需要提醒大家的是,仓库的添加顺序直接决定了构件的下载顺序,换句话来说我们应该把需要从中央仓库或者其他远程仓库下载构件的代理仓库添加在最后。
当咱们成功将指定的仓库集合添加进仓库组后,接下来我们来为3rd party(宿主仓库)上传自定义构件,所谓自定义构件指的是无法从Maven的中央仓库进行下载的构建。
笔者在此选用的是最简单方便的手动上传构件(当然上传构件至宿主仓库还有一些方式,但笔者还是侧重于最简便的方式)。
单击3rd party(宿主仓库)的Artifact Upload选项,我们首先来上传一个基于Maven项目的自定义构件:
最后别忘记了添加构件:
如果你的构件不是基于Maven的呢?那么你可以选择GAV Parameters属性:
接下来,需要配置 Maven 来连接到似有仓库,如果需要全局配置,则配置地址为 ~\.m2\setting.xml,如果需要根据工程配置,则需要跟pom.xml在同一个目录下面即可,文件存在则修改,不存在则创建,内容如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<profiles> <profile> <id>dev</id> <repositories> <repository> <id>nexus</id> <url>http://127.0.0.1:8080/nexus/content/groups/public/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>nexus</id> <url>http://127.0.0.1:8080/nexus/content/groups/public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>true</enabled> </snapshots> </pluginRepository> </pluginRepositories> </profile> </profiles> <activeProfiles> <activeProfile>dev</activeProfile> </activeProfiles> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
[Default Applications] application/csv=gnumeric.desktop application/excel=ooo-calc.desktop application/msexcel=ooo-calc.desktop application/msword=ooo-writer.desktop application/ogg=mplayer.desktop application/pdf=evince.desktop application/postscript=evince.desktop ................. text/x-chdr=vim.desktop text/x-csrc=vim.desktop text/x-dtd=vim.desktop text/x-java=vim.desktop text/mathml=vim.desktop text/x-python=vim.desktop text/x-sql=vim.desktop text/xml=firefox.desktop video/dv=mplayer.desktop video/mp4=mplayer.desktop video/mpeg=mplayer.desktop video/msvideo=mplayer.desktop video/quicktime=mplayer.desktop video/vnd.rn-realvideo=mplayer.desktop video/x-anim=mplayer.desktop video/x-avi=mplayer.desktop video/x-flc=mplayer.desktop ...................... |
Windows Platform Design Notes
Design Information for the Microsoft® Windows® Family of Operating Systems
Debugging NDIS Drivers
Abstract
This paper provides information about debugging Network Driver Interface Specification (NDIS) drivers for the Microsoft® Windows® family of operating systems. It provides guidelines for the NDIS driver developer to identify commonly encountered issues in network drivers and specifies best practices that will help the driver developer avoid network driver issues in the first place. This paper also provides information on how to use Ndiskd.dll, the NDIS kernel debugger extension, to gather information about the state of NDIS and the NDIS drivers.
Contents
Using Ndiskd.dll to Debug NDIS Drivers. 4
Debugging a Miniport Initialization Problem.. 12
Debugging the Failure of a Miniport to Halt13
Debugging Power Management Issues. 14
Debugging Interrupt Storms. 15
Best Practices for Developing Miniport Drivers. 16
Tools – Using NDISTest and Driver Verifier16
Best Practices for Developing Intermediate Drivers. 17
Common Intermediate Driver Issues. 17
Best Practices for Developing Protocol Drivers. 18
Call to Action and Resources. 18
This is a preliminary document and may be changed substantially prior to final commercial release of the software described herein.
The information contained in this document represents the current view of Microsoft Corporation on the issues discussed as of the date of publication. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information presented after the date of publication.
This White Paper is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS DOCUMENT.
Complying with all applicable copyright laws is the responsibility of the user. Without limiting the rights under copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of Microsoft Corporation.
Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property.
Unless otherwise noted, the example companies, organizations, products, domain names, e-mail addresses, logos, people, places and events depicted herein are fictitious, and no association with any real company, organization, product, domain name, e-mail address, logo, person, place or event is intended or should be inferred.
® 2003 Microsoft Corporation. All rights reserved.
Microsoft, Windows, and Windows Server are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.
The names of actual companies and products mentioned herein may be the trademarks of their respective owners.
This paper provides information about debugging NDIS drivers for the Microsoft® Windows® family of operating systems. It also provides coding practices that driver developers can use to avoid common problems encountered by NDIS drivers such as initialization failures in NDIS miniports, NDIS Intermediate drivers whose miniports do not get halted, and other common issues reported to the NDIS team at Microsoft. The paper discusses:
Note: The information presented in this paper is applicable to Microsoft Windows Server™ 2003 driver development. Most of the information also applies to Microsoft Windows XP and Microsoft Windows 2000.
This paper assumes that you are familiar with the basic NDIS model. In addition to the miniports and protocols that have been discussed in the Microsoft Windows Driver Development Kit (DDK), this paper introduces the MOpen structure that represents a binding between a protocol and a miniport. The model, including the MOpen structure, appears in figure 1.
Figure 1: NDIS diagram including the MOpen structure
Developers and testers at Microsoft Corporation use Ndiskd.dll to quickly analyze potential network driver issues. Ndiskd.dll is a part of the Microsoft Debugging Tools package for kernel-mode debugging. Ndiskd.dll runs on both WinDBG.exe and Kd.exe, and it provides basic and detailed information about a miniport driver and the protocol drivers that are bound to it.
The most commonly used Ndiskd.dll commands are !miniports and !miniport <MiniportAdapterHandle>. Use the !miniports command to print all of the NDIS miniports that are present in the system. Use the !miniport <MiniportAdapterHandle> command to print detailed information about a miniport adapter, including the protocols it is bound to and the miniport’s PnP and power management states.
The following example shows how to get detailed information about a particular protocol that is bound to the Sample Ethernet Driver miniport. The Sample Ethernet Driver is a real NDIS miniport driver that has been given a fictitious name.
1 2 3 4 5 6 7 |
0: kd> !miniports NDIS Driver Verifier level: 0 NDIS Failed allocations : 0 Miniport Driver Block: 80d883c0, Version 0.0 Miniport: 80dbb130 1394 Net Adapter Miniport Driver Block: 80dc7c30, Version 4.25 Miniport: 80dc76f0Sample Ethernet Driver |
To print detailed information about the Sample Ethernet Driver, use the !miniportcommand. The pointer in bold in the preceding example is the argument to !miniport.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
0: kd> !miniport 80dc76f0 Miniport 80e16130 : Sample Ethernet Driver AdapterContext : 80cd52c0 Flags : 2c412048 BUS_MASTER, SG_LIST, IGNORE_TOKEN_RING_ERRORS RESOURCES_AVAILABLE, SUPPORTS_MEDIA_SENSE, DOES_NOT_DO_LOOPBACK, MEDIA_CONNECTED, PnPFlags : 00210000 RECEIVED_START, HARDWARE_DEVICE, InternalResetCount : 0000 MiniportResetCount : 0000 References : 3 UserModeOpenReferences: 0 PnPDeviceState : PNP_DEVICE_STARTED CurrentDevicePowerState : PowerDeviceD0 Bus PM capabilities DeviceD1: 1 DeviceD2: 1 WakeFromD0: 0 WakeFromD1: 1 WakeFromD2: 1 WakeFromD3: 1 SystemState DeviceState PowerSystemUnspecified PowerDeviceUnspecified S0 D0 S1 PowerDeviceUnspecified S2 PowerDeviceUnspecified S3 D3 S4 D3 S5 D3 SystemWake: PowerSystemUnspecified DeviceWake: PowerDeviceUnspecified Current PnP and PM Settings: : 00000030 DISABLE_WAKE_UP, DISABLE_WAKE_ON_RECONNECT, Allocated Resources: IO Port: 0000ec00, Length: 80 Memory: fe004000, Length: 80 Interrupt Level: 44, Vector: 44 Translated Allocated Resources: IO Port: 0000ec00, Length: 80 Memory: fe004000, Length: 80 Interrupt Level: 9, Vector: 1a3 MediaType : 802.3 DeviceObject : 80e16030, PhysDO : 80e939a0 Next DO: 80e939a0 MapRegisters : 00000000 FirstPendingPkt: 00000000 DriverVerifyFlags : 00000000 Miniport Interrupt : 80cd5530 Miniport Open Block Queue: 80d066b0: Protocol 80ceb978 = TCPIP, ProtocolBindingContext 80d21a50 80db44c0: Protocol ffb54478 = NDISUIO, ProtocolBindingContext 80ceff58 |
Use the !mopen command to print detailed information about an Mopen structure, or binding, between the Sample Ethernet Driver and a protocol. Use the pointers in bold from the preceding example as arguments for the !mopen command.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
0: kd> !mopen 80db44c0 Miniport Open Block 80db44c0 Protocol ffb54478 = NDISUIO, ProtocolContext 80ceff58 Miniport 80dc76f0 = Sample Ethernet Driver MiniportAdapterContext: 80cd52c0 Flags : 00000000 References : 1 0: kd> !mopen 80d066b0 Miniport Open Block 80d066b0 Protocol 80ceb978= TCPIP, ProtocolContext 80d21a50 Miniport 80dc76f0 = Sample Ethernet Driver MiniportAdapterContext: 80cd52c0 Flags : 00000000 References : 1 |
To print information about the protocol structures use the !protocol command. Use the pointer in bold from the preceding example as the argument to the !protocol command.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
0: kd> !protocol ffb54478 Protocol ffb54478 : NDISUIO RootDeviceName is \DEVICE\{9C358E9A-BC5E-4A71-A8B6-993A0D3B404D} RefCount 2 Open 80db44c0 - Miniport: 80dc76f0 Sample Ethernet Driver BindAdapterHandler fb1a6e56, UnbindAdapterHandler fb1a6a30 PnPEventHandler fb1a67c2, UnloadHandler 00000000 OpenAdapterComplete fb1a6224, CloseAdapterComplete fb1a6242 SendCompleteHandler fb1a78c0, TransferDataComplete fb1a75d2 ReceiveHandler fb1a770c, ReceivePacketHandler fb1a7636 ReceiveComplete fb1a6514, StatusHandler fb1a64c4 StatusComplete fb1a6514 AssociatedMiniDriver 00000000 Flags : 00000000 |
The preceding example shows how to use the list of miniport drivers in the system to get detailed information about the protocols that are bound to a miniport adapter. The example printed four sets of information:
Note: For detailed information about Ndiskd.dll, see the Help file provided with the Microsoft Debugging Tools, and the Microsoft Windows Driver Development Kit (DDK).
Three useful debugger extensions exist that are not well known:
Ndiskd.dll includes the !pkt and !findpacket commands. The !stacks command is part of the Microsoft Debugging Tools package and is not included in Ndiskd.dll.
The !pkt command prints out detailed information about an NDIS_PACKET structure. You can specify a verbosity level to control the amount of information that the debugger prints, as shown in the following code.
1 2 3 4 |
kd> !ndiskd.pkt 817b03f8 5 Usage: pkt <pointer to packet> <verbosity> 1-Packet Private, 2-Packet Extension 3-Ndis Reference, 4-Buffer List |
To print every NDIS_BUFFER structure in an NDIS_PACKET structure, use a verbosity level of 4:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
kd> !ndiskd.pkt 817b03f8 4 NDIS_PACKET at 817b03f8 NDIS_BUFFER at 816bb104 Next 816bc054 Size 20 MdlFlags 4 Process 00000000 MappedSystemVa 816bb124 Start VA 816bb000 ByteCount e ByteOffset 124 NDIS_BUFFER at 816bc054 Next 816480d0 Size 20 MdlFlags 4 Process 00000000 MappedSystemVa 816bc074 Start VA 816bc000 ByteCount 14 ByteOffset 74 NDIS_BUFFER at 816480d0 Next 00000000 Size 20 MdlFlags 1004 Process 00000000 MappedSystemVa 81648110 Start VA 81648000 ByteCount 14 ByteOffset 110 MacReserved[]: 00000000 00000000 00000000 00000000 0. TcpIpChecksumPacketInfo = 00000000 1. IpSecPacketInfo = 00000000 2. TcpLargeSendPacketInfo = 00000000 3. ClassificationHandlePacketInfo = 00000000 4. NdisReserved = 00000000 5. ScatterGatherListPacketInfo = 00000000 6. Ieee8021pPriority = 00000000 7. OriginalPacketInfo = 817b03f8 8. PacketCancelId = 00000000 9. MaxPerPacketInfo = 00000000 Packet.Private PhysicalCount 00000001 Total Length 00000028 Head 816bb104 Tail 816480d0 Pool 817b36a0 Count 00000001 Flags 00000002 ValidCounts 00 NdisPacketFlags 00000080 NdisPacketOobOffset 006c Private.Flags : 00000002 Private.NdisPacketFlags: 80 fPACKET_ALLOCATED_BY_NDIS, |
The preceding example prints every NDIS_BUFFER structure in a particular NDIS_PACKET structure, as well as the Out-Of-Band(OOB) information in the NDIS_PACKET structure.
The !findpacket -p command finds all the packets that are allocated from a particular packet pool and that are currently in use by the miniport driver. Intermediate (IM) driver developers can use the findpacket -p command to list all of the packets that are allocated by the IM driver and indicated up to the protocols.
The following example shows how to locate all of the packets that are currently allocated in a packet pool. You need to pass the packet pool’s PoolHandle, that was returned to the NDIS driver when it called the NdisAllocatePacketPoolEx function, as the argument to the !findpacket -p command, as shown below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
kd> !ndiskd.findpacket p 816d4e68 Searching Free block <0x816d0000> Packet at 0x816d0058 Packet at 0x816d0120 Packet at 0x816d01e8 Packet at 0x816d02b0 Packet at 0x816d0378 Packet at 0x816d0440 Packet at 0x816d0508 Packet at 0x816d05d0 Packet at 0x816d0698 Packet at 0x816d0760 Packet at 0x816d0828 Packet at 0x816d08f0 Packet at 0x816d09b8 Packet at 0x816d0a80 Packet at 0x816d0b48 Packet at 0x816d0c10 Packet at 0x816d0cd8 Packet at 0x816d0da0 Packet at 0x816d0e68 |
Use the !stacks command to find hung threads and to debug other difficult problems. This extension is present in the Debugger package but is not a part of ndiskd.dll.
You can specify a character string as an argument to the !stacks command. The debugger prints all the threads that contain the character string in their stacks. For example, the command !stacks 2 ndis! causes the debugger to print every thread that contains the “ndis!” string in its stack.
The threads printed by the debugger can provide important clues that will help you solve the problem you are investigating. For example, the output in the following code was taken from an IM driver that was not completing any requests to send packets. When the miniport adapter was disabled, the underlying miniport adapter was never halted as TCP/IP waited for the IM driver to complete the sends. The output, which is the result of the !stacks 2 ndis! command, contains two threads: one that shows TCP/IP waiting for outstanding sends to complete, and another that is an NDIS thread reserved for system use.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
0: kd> !stacks 2 ndis! Proc.Thread .Thread Ticks ThreadState Blocker [80e76648 System] 4.00003c 80e738a0 0001f02 Blocked nt!KiSwapContext+0x26 nt!KiSwapThread+0x280 nt!KeWaitForSingleObject+0x249 tcpip!TCPCleanup+0xcc tcpip!TCPDispatch+0x91 nt!IofCallDriver+0x3f nt!IopCloseFile+0x27c nt!ObpDecrementHandleCount+0x121 nt!ObpCloseHandleTableEntry+0x12f nt!ObpCloseHandle+0x80 nt!NtClose+0x17 nt!_KiSystemService+0xd0 nt!ZwClose+0x11 netbt!DelayedNbtCloseFileHandles+0x4b netbt!CloseAddressesWi…+0x10b netbt!NbtNewDhcpAddress+0x69 netbt!TdiAddressDeletion+0x82 TDI!TdiNotifyPnpClientList+0xd7 TDI!TdiExecuteRequest+0x25b TDI!TdiHandleSerializedRequest+0x1c2 TDI!TdiDeregisterNetAddress+0xb tcpip!NotifyAddrChange+0x109 tcpip!IPpSetNTEAddr+0xde tcpip!IPDelNTE+0x39 tcpip!IPDelInterface+0xdf tcpip!ARPUnbindAdapter+0x70 NDIS!ndisUnbindProtocol+0x151 NDIS!ndisCloseMiniportBindings+0x201 NDIS!ndisPnPRemoveDevice+0x128 NDIS!NdisIMDeInit…DeviceInst…+0x40 passthru+0x2dc3 NDIS!ndisUnbindProtocol+0x151 NDIS!ndisCloseMiniportBindings+0x201 NDIS!ndisPnPRemoveDevice+0x128 NDIS!ndisPnPDispatch+0x15b nt!IofCallDriver+0x3f nt!IopSynchronousCall+0xc0 nt!IopRemoveDevice+0x89 nt!IopRemoveLockedDeviceNode+0x15e nt!IopDeleteLockedDeviceNode+0x32 4.00007c 80e04da0 0000129 Blocked nt!KiSwapContext+0x26 nt!KiSwapThread+0x280 nt!KeRemoveQueue+0x29b NDIS!ndisWorkerThread+0x2e nt!PspSystemThreadStartup+0x2e nt!KiThreadStartup+0x16 |
The preceding example shows the benefit of running the !stacks 2 ndis! command, which provides useful clues about the current state of the computer. In the example, you can see that TCP/IP is waiting for an event. It is reasonable to assume that it is waiting for outstanding sends. Later in this paper, you will see how this assumption can be verified.
The second thread printed in the preceding example is reserved for system use.
Use the !stacks 2 <miniport driver name> command to print all the threads with the miniport driver’s name in their stacks.
NDIS has debug messages built into its checked version. By default, these are not printed in the debugger and need to be turned on. Use NDIS tracing to analyze problems that are not in the data path, such as PnP and power-management problems. NDIS tracing works on both free and checked builds of the operating system.
The following example demonstrates how to turn on the NDIS tracing feature in the REQUEST code path at the INFO level within NDIS. There are four levels of debug messages available to the developer: Info, Warn, Err and Fatal. The Info level is the most verbose, and the Fatal level is the least verbose. (The Log level has not been implemented.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
0: kd> !ndiskd.dbglevel Current setting:FATAL Available settings: INFO LOG WARN ERR 0: kd> !ndiskd.dbglevel INFO 0: kd> !ndiskd.dbgsystems Current settings: Available settings: INIT CONFIG SEND RECV PROTOCOL BIND BUS_QUERY REGISTRY MEMORY FILTER REQUEST WORK_ITEM PNP PM OPEN LOCKS RESET WMI NDIS_CO REFERENCE 0: kd> !ndiskd.dbgsystems REQUEST BIND Arg = REQUEST Arg = BIND 0: kd> g ***NDIS*** (c, 56) ==>ndisMRequest ***NDIS*** (c, 89) ndisMRequest: Queueing request 0xfc8fbc68 ***NDIS*** (c, 392) ==>ndisMDoRequests ***NDIS*** (c, 419) ndisMDoRequests: Processing Request 0xfc8fbc68, Oid 0xff00c913 ***NDIS*** (c, 2473) ==>ndisMSyncQueryInformationComplete ***NDIS*** (c, 2503) ndisMSyncQueryInformaitonComplete: Request 0xfc8fbc68, Oid 0xff00c913 |
The Dbglevel and Dbgsystems settings are toggle settings. To turn off the debug print feature for the REQUEST and BIND code paths, you must re-enter the previous command, as shown here:
1 2 3 4 5 6 7 8 9 10 11 |
0: kd> !ndiskd.dbgsystems REQUEST BIND Arg = REQUEST Arg = BIND 0: kd> !ndiskd.dbgsystems Current settings: Available settings: INIT CONFIG SEND RECV PROTOCOL BIND BUS_QUERY REGISTRY MEMORY FILTER REQUEST WORK_ITEM PNP PM OPEN LOCKS RESET WMI NDIS_CO REFERENCE |
The preceding example shows how you can set and reset the verbosity and component values, which control the level of debugging information that NDIS prints in the debugger.
The system performs a bug check when it detects an error caused by an NDIS miniport driver. The bug check is performed as soon as an error is detected. If the system did not stop, these errors would appear later, making it difficult to pinpoint the cause of the problem at that stage.
The bug checks that are caused by an NDIS miniport driver use a special bug check code. On Windows XP and Windows 2000, the bug check code is BUGCODE_ID_DRIVER. On Windows Server 2003, the bug check code is BUGCODE_NDIS_DRIVER. If a debugger is connected to the system being tested, a sentence describing the bug check is printed in the debugger. The !analyze –v command provides detailed information on the bug check.
Examples of NDIS miniport driver problems that cause the system to perform a bug check include the following:
Note: For more information about bug check codes, see the Debugger.chm help file in the Microsoft Debugging Tools package.
NDIS implements the following Plug and Play (PnP) functionality on behalf of the miniport:
The !ndiskd.miniport command prints information that is useful for debugging PnP problems, as shown in the following example.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
0: kd> !miniport 80dc76f0 Miniport 80e16130 : Sample Ethernet Driver AdapterContext : 80cd52c0 Flags : 2c412048 BUS_MASTER, SG_LIST, IGNORE_TOKEN_RING_ERRORS RESOURCES_AVAILABLE, SUPPORTS_MEDIA_SENSE, DOES_NOT_DO_LOOPBACK, MEDIA_CONNECTED, PnPFlags : 00210000 RECEIVED_START, HARDWARE_DEVICE, InternalResetCount : 0000 MiniportResetCount : 0000 References : 3 UserModeOpenReferences: 0 PnPDeviceState : PNP_DEVICE_STARTED CurrentDevicePowerState : PowerDeviceD0 Bus PM capabilities DeviceD1: 1 DeviceD2: 1 WakeFromD0: 0 WakeFromD1: 1 WakeFromD2: 1 WakeFromD3: 1 SystemState DeviceState PowerSystemUnspecified PowerDeviceUnspecified S0 D0 S1 PowerDeviceUnspecified S2 PowerDeviceUnspecified S3 D3 S4 D3 S5 D3 SystemWake: PowerSystemUnspecified DeviceWake: PowerDeviceUnspecified Current PnP and PM Settings: : 00000030 DISABLE_WAKE_UP, DISABLE_WAKE_ON_RECONNECT, Allocated Resources: IO Port: 0000ec00, Length: 80 Memory: fe004000, Length: 80 Interrupt Level: 44, Vector: 44 Translated Allocated Resources: IO Port: 0000ec00, Length: 80 Memory: fe004000, Length: 80 Interrupt Level: 9, Vector: 1a3 MediaType : 802.3 DeviceObject : 80e16030, PhysDO : 80e939a0 Next DO: 80e939a0 MapRegisters : 00000000 FirstPendingPkt: 00000000 DriverVerifyFlags : 00000000 Miniport Interrupt : 80cd5530 Miniport Open Block Queue: ffb31d18: Protocol ffb57cf8 = NDISUIO, ProtocolBindingContext ffb323e8 ffbad958: Protocol 80e15998 = TCPIP, ProtocolBindingContext ffbadc00 |
The !miniport extension prints a lot of useful information. The items that the previous example prints include the following:
Miniport adapters can fail to initialize for a variety of reasons. If the problem is reproducible, the best way to proceed is to turn on NDIS tracing and reproduce the problem. The debug messages printed in the debugger makes it easy to identify the point of failure.
To debug a miniport initialization problem:
The following example contains the debugging messages that are printed during the initialization of a miniport adapter.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<==ndisAddDevice: Miniport 81AF6338 ndisPnPAddDevice returning 0 ==>ndisPnPStartDevice: DeviceObject ndisPnPStartDevice: Miniport 81AF6338, Sample Ethernet Driver … ==NdisMQueryAdapterResources: Miniport 81AF6338, Status 0 ==>NdisMRegisterIoPortRange: Miniport 81AF6338 ==>ndisTranslateResources: Miniport 81AF6338 translating resource type: 1, value: 1800 ndisTranslateResources translated 1800 to 1800 <==ndisTranslateResources: Miniport 81AF6338, Status 0 <==NdisMRegisterIoPortRange: Miniport 81AF6338, Status 0 ==>NdisWriteErrorLogEntry <==NdisWriteErrorLogEntry ==>NdisMDeregisterIoPortRange: Miniport 81AF6338 <==NdisMDeregisterIoPortRange: Miniport 81AF6338 ndisMInitializeAdapter: Miniport 81AF6338, InitializeHandler returned c0000001 ==>NdisMDeregisterAdapterShutdownHandler: Miniport 81AF6338 <==NdisMDeregisterAdapterShutdownHandler: Miniport 81AF6338 ***NDIS*** (b, 1791) INIT FAILURE: Dequeueing the miniport from the driver block. ==>ndisDeQueueMiniportOnDriver, Miniport 81AF6338, MiniBlock 81BB7588 <==ndisDeQueueMiniportOnDriver: Miniport 81AF6338, MiniBlock 81BB7588 ***NDIS*** (b, 1822) INIT FAILURE: Dereferencing the miniport block. |
The preceding example shows a miniport adapter failing its initialization routine. In the beginning of the example, NDIS gets called at its AddDevice routine for the miniport, followed by a StartDevice IRP. As part of the IRP, NDIS calls the MiniportInitialize function handler, which fails because of an error that occurred after it successfully called the NdisMRegisterIoPortRange function. You can use this information as the starting point for debugging the initialization problem. NDIS debug messages also tell you if the NDIS API failed and possibly why it failed.
If NDIS does not call a miniport driver’s MiniportHalt function when the miniport adapter is disabled through the user interface or an automated test, it is usually because an operation that the miniport driver must complete before being halted has not completed. For example, NDIS will not halt a miniport adapter until the driver finishes sending all the packets that were sent to it for transmission.
To debug the failure of a miniport to halt:
The following example shows an MOpen structure between the NDISUIO protocol and the Sample Ethernet Driver miniport.
1 2 3 4 5 6 7 8 9 |
0: kd> !mopen ffaefd70 Miniport Open Block ffaefd70 Protocol ffae6ad8 = NDISUIO, ProtocolContext ffaeb2e8 Miniport 80d74698 = Sample Ethernet Driver MiniportAdapterContext: 80ccb008 Flags : 00218010 OPEN_PROCESSING, OPEN_CLOSING, OPEN_UNBINDING OPEN_DONT_FREE, References : 43 |
The preceding example shows an Mopen structure between the NDISUIO protocol and the Sample Ethernet Driver. NDIS has called the protocol’s ProtocolUnbindAdapter handler.The protocol has called the NdisCloseAdapter function. NDIS will not call the protocol’s CloseAdapterComplete handler until the number of references reaches zero. The references are caused by outstanding send commands in the miniport.
As the device power policy owner of the miniport, NDIS is responsible for querying the bus driver, the miniport driver, and the system settings before deciding on the power management policy for the miniport adapter.
To find the values returned by the bus driver and the miniport driver, turn on NDIS tracing or look at the output of the !miniport command:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
0: kd> !miniport 80dc76f0 Miniport 80e16130 : Sample Ethernet Driver AdapterContext : 80cd52c0 Flags : 2c412048 BUS_MASTER, SG_LIST, IGNORE_TOKEN_RING_ERRORS RESOURCES_AVAILABLE, SUPPORTS_MEDIA_SENSE, DOES_NOT_DO_LOOPBACK, MEDIA_CONNECTED, PnPFlags : 00210000 RECEIVED_START, HARDWARE_DEVICE, InternalResetCount : 0000 MiniportResetCount : 0000 References : 3 UserModeOpenReferences: 0 PnPDeviceState : PNP_DEVICE_STARTED CurrentDevicePowerState : PowerDeviceD0 Bus PM capabilities DeviceD1: 1 DeviceD2: 1 WakeFromD0: 0 WakeFromD1: 1 WakeFromD2: 1 WakeFromD3: 1 SystemState DeviceState PowerSystemUnspecified PowerDeviceUnspecified S0 D0 S1 PowerDeviceUnspecified S2 PowerDeviceUnspecified S3 D3 S4 D3 S5 D3 SystemWake: PowerSystemUnspecified DeviceWake: PowerDeviceUnspecified Current PnP and PM Settings: : 00000030 DISABLE_WAKE_UP, DISABLE_WAKE_ON_RECONNECT, Allocated Resources: IO Port: 0000ec00, Length: 80 Memory: fe004000, Length: 80 Interrupt Level: 44, Vector: 44 Translated Allocated Resources: IO Port: 0000ec00, Length: 80 Memory: fe004000, Length: 80 Interrupt Level: 9, Vector: 1a3 MediaType : 802.3 DeviceObject : 80e16030, PhysDO : 80e939a0 Next DO: 80e939a0 MapRegisters : 00000000 FirstPendingPkt: 00000000 DriverVerifyFlags : 00000000 Miniport Interrupt : 80cd5530 Miniport Open Block Queue: ffb31d18: Protocol ffb57cf8 = NDISUIO, ProtocolBindingContext ffb323e8 ffbad958: Protocol 80e15998 = TCPIP, ProtocolBindingContext ffbadc00 |
In the preceding example, NDIS sets the DISABLE_WAKE_UP flag, because the user has not enabled Wake-On-LAN (WOL) for this miniport adapter. To debug a WOL problem, you need to inspect the power management values returned by the system, the bus driver, and the miniport to determine which of the three entities is disabling WOL. These values are all displayed in the output of the !miniport command.
Interrupt storms occur when either a miniport driver fails to disable device interrupts or the device continues to assert an interrupt after that interrupt has been disabled. In either case, the computer is not usable until the device stops asserting interrupts.
To diagnose an interrupt storm problem:
When a miniport driver calls the NdisMResetComplete function, NDIS completes all outstanding requests on behalf of the driver. If that driver is a serialized driver, NDIS also returns all the send packets that NDIS has queued for the driver to the appropriate protocol drivers.
The following practices are followed by developers at Microsoft Corporation when developing NDIS drivers:
NDISTest and Verifier.exe are good tools to use when developing NDIS drivers. NDISTest aids and verifies the completeness of a miniport driver. You should use it on both miniports and IM drivers. NDISTest cannot test protocols. Use Driver Verifier to ensure that common errors are easily found and rectified early in the development cycle.
Use Driver Verifier from the beginning of the development effort. Use NDISTest to test the functional completeness and robustness of the driver. You can run an individual test from the test suite to test specific features of the NDIS driver.
The __LINE__ compiler directive is a useful tool. The compiler replaces each __LINE__ directive with the actual line number in the file, which is useful for logging or printing debugging messages.
You can enhance a deserialized driver to track the acquisition and release of spin locks by recording each file and line number that acquired a spin lock. This record is cleared just before releasing the spin lock.
At the beginning of each .c file, include a #define statement that uniquely identifies the file, as shown in the following code. Be sure that the defined value is larger than the number of lines that a file could contain, because the line number and the file number will be combined into a single unsigned integer.
1 |
#define DRIVER_FILE 0x0010000 |
Define the following structures and macros in a header file of the driver:
1 2 3 4 5 6 7 8 9 10 11 12 |
typedef struct _SAMPLE_DRIVER_LOCK{ NDIS_SPIN_LOCK SpinLock; ULONG Location; } SAMPLE_DRIVER_LOCK, *PSAMPLE_DRIVER_LOCK; #define MiniportAcquireLock(_Lock) \ NdisAcquireSpinLock (&((_Lock)->NdisSpinLock));\ (_Lock)->Location = (DRIVER_FILE + __LINE__); #define MiniportReleaseSpinLock(_Lock) \ (_Lock)->Location = 0;\ NdisReleaseSpinLock(&((_Lock)->NdisSpinLock)); \ |
The preceding structure and two macros enable you to quickly find the line of code that last acquired the spin lock. To verify that no spin-lock issues exist in the code, run Driver Verifier with the Deadlock Detection option turned on. Each acquisition of a spin lock will be tested to make sure that it occurred in the right order with respect to all the other spin locks in your driver.
An NDIS IM driver is complex, because any of the entry points in the driver’s protocol module or miniport module can be called regardless of the state of the other module.
The IM driver must ensure that a notification, such as a send or receive command to one of its modules, does not result in an incorrect action from its other module. For example, when NDIS requests that an IM driver’s miniport module should send a packet, the driver must then determine whether the protocol module can propagate the packet down or if the packet needs to fail.
You should maintain a reference count on all outstanding actions that the IM driver will be called back for—actions such as send commands and requests that the driver initiates to the miniport below it. This reference count should be synchronized with the unbind code in the protocol. The IM miniport should also maintain a reference count of the number of outstanding receive commands that the IM driver has indicated. This count must be synchronized with the PnP code path in the IM miniport driver, to ensure that no receive commands occur after the IM miniport adapter has been halted.
When developing an IM driver, you might encounter the problem of TCP/IP not sending packets to the IM driver for transmission. Common causes of this problem include the following:
You should run NDISTest on the IM driver to solve such problems.
Another problem is that outstanding send and request commands in the IM miniport module can prevent NDIS from calling an IM driver’s MiniportHalt routine after the driver has called the NdisIMDeInitializeDeviceInstance function. In this situation, the IM driver could have passed such a packet to the miniport adapter below it, or queued the packet internally. The Mopen structure can determine whether any packets were passed to the underlying miniport.
The problems that commonly occur with protocol drivers are similar to those that occur with IM drivers. As described earlier, it is important to synchronize the protocol driver’s PnP code path with the driver’s send code path.
Use the appropriate I/O Control (IOCTL) codes when designing the protocol driver’s IOCTL interface. IOCTLs should specify the METHOD_BUFFERED option as documented in the DDK and have the appropriate read or write privilege set in the IOCTL code. If an IOCTL is going be used only when an Administrator is logged on, the protocol driver should create a device object by calling the IoCreateDeviceSecure routine.
Call to Action:
For questions about debugging and developing NDIS drivers, post questions on the public Microsoft device driver newsgroup.
For specific questions about this paper, send e-mail to ndis6fb@microsoft.com.
Resources:
Microsoft Hardware and Driver Developer Information
http://www.microsoft.com/hwdev/
Microsoft Windows Driver Development Kit (DDK)
Microsoft Debugging Tools
http://www.microsoft.com/ddk/debugging/default.asp
Microsoft’s public device driver newsgroup
microsoft.public.development.device.drivers
WD My Cloud 的内存只有256M,在安装一系列应用之后,往往会导致内存不足,尤其是磁盘对拷的时候,很大的文件,往往会导致 Linux 内核的 OOM-Killer动作,导致 sshd ,Apache 等的服务被杀死,此时系统的指示灯是正常的,但是网络响应全无,只能强制断电。
先简单讲一下OOM-Killer的原理
OOM-killer:Out-of-Memory (OOM) Killer是一种保护机制,用于当内存严重不足时,为了系统的继续运转,内核迫不得已挑选一个进程,将其杀死,以释放内存,缓解内存不足的问题。
可以看出这种方式对进程的保护是有限的,不能完全的保护进程的运行。
OOM Killer的关闭与激活方式:
1 2 3 |
# echo "0" > /proc/sys/vm/oom-kill # echo "1″ > /proc/sys/vm/oom-kill |
在实际运营场景中,我们经常出现ssh连接不上服务器,但ping却是通的情况,这个时候很有可能是内存不够linux启动了oom-killer,系统根据一定的分数和机制来决定
随机杀掉一些程序释放物理内存(特别是我们后台需要大量共享内存而且用了mlock的程序),而sshd进程很可能就是被选中杀掉的进程,因此导致通过ssh登录不上。
这个时候基本上swap也被耗尽, 所有能释放内存的机制内核都已经尝试了。
而ping能够通,主要是因为ping其实是内核协议栈就直接回包了,不会走到用户态,所以还能证明机器还是活着的。
对于每个进程都有一个oom_score的属性/proc/PID/oom_score
oom- killer 会杀死oom_score较大的进程,当oom_score为0时禁止内核杀死该进程。
还有一个/proc/PID/oom_score_adj
一般来说,oom_adj的值越大,该进程被系统选中终止的可能就越高,当oom_adj=-17时,oom_score将变为0。
(要对某个进程进行OOM保护的话就直接向“/proc/pid/oom_adj”中写入“-17”即可。)
所以可以通过命令
1 |
$ echo 0 > /proc/PID/oom_score_adj |
来防止重要的进程被oom_killer杀死。
例如可以把sshd进程的oom_adj改为0 ,包括自己连接上的那个终端进程,这样你还可以执行一些运维工作。
既然了解到这些,那么操作方式就很简单了。
为了防止SSHD被杀死,可以在命令行中执行如下命令
1 |
$ pgrep -f "/usr/sbin/sshd" | while read PID; do echo -17 > /proc/$PID/oom_score_adj;done |
为保万无一失,利用Linux的计划任务cron来做一下定时检查。
1 |
$ sudo vim /etc/cron.d/sshd_oom_disabled |
里面内容如下
1 2 |
#/etc/cron.d/sshd_oom_disable */10**** root pgrep -f "/usr/sbin/sshd" | while read PID;do echo -17 > /proc/$PID/oom_score_adj;done |
表示每10分钟执行一次进程存在检查。