用root精灵:RootGenius2.0.1.3获取到联想lenovo A785e root权限。

用root精灵:RootGenius2.0.1.3获取到联想lenovo A785e root权限。

Android版本:v4.3

内核版本:3.4.0

版本号:A785e_S021_140430

如何开启联想lenovo A785e USB调试选项

在设置-关于手机-连续点击版本号可以打开开发者选项

如果root失败,可以参考该url,尝试其他root工具:http://www.rootzhushou.com/ndetail/36.html

发表在 Linux驱动开发 | 标签为 | 留下评论

程序员在开发过程中,提高android程序运行效率应当注意的事项

1 介绍

无论开发什么产品,效率都是最重要的,安卓程序的效率也一样,如果你做出一款登录很慢,延时很长的产品,相信很多人都不愿意再打开,可能直接就删除了。

那么如何提高Android程序的运行效率,也就是说如何来优化Android的性能呢?下面提供给你一些想法,希望能够给广大安卓开发者带来灵感:

在程序的开发过程中,为节省系统资源,有两条基本的原则:

(1)开发过程中,你只实现你所需要的功能;

(2) 能避免占用内存时,就一定不要去占用内存;

以下所应注意的事项都是基于这两条原则上的。

也许有些人会提出,基于此原则将很难达到真正目的的优化。但我们也必须承认,在像开发手机这样的嵌入式设备上,有时,我们没有其它的选择,为了有一些小的优化,很难开发出高效的数据结构和算法的。例如,当你把你的想法在 android的模拟器上来进行实现时,你有可能因为没有注意,写得代码是以耗尽系统几乎所有内存为代价的.当你把程序上传到真机上时,此时,你的程序将运行的效率很低,很难达到用户的要求。

所以,下面要介绍的一些事项能够,它可以在程序开发中,指导我们的编码,只有这样,程序才能安全执行,运行效率才能提高。

2. 避免创建对象

对象的创建都是要占用资源的,如果你在循环程序中创建对象,由于过多的占用内存,你将定时的启动内容回收机制,从而降低了运行速度。

所以,当你不需要时,你应该避免创建类实例,给出以下几个例子作为说明:

尽量避免使用字符串,例如:从JSP或是其他客户端得到某些信息,其中包含int,Date,String类型,尽早把它们转化为自己合适的数据类型。

必须使用字符串时,考虑 当字符串不可变化时,使用String类型;当可变时使用StringBuffer类型。

当需要字符串+时,使用StringBuffer。这些例子大家可以在“动态对象管理”的DAO实现类中找到。

String s = “aaa” + “bbb”;

上面的语句实际上创建了三个String对象,性能受损。

StringBuffer s= new StringBuffer();

s.append(“aaa”);

s.append(“bbb”);

上面仅仅创建一个对象。

3. 多使用原始的方法

当处理字符串时,应该多的使用像String.indexOf(),String.lastIndex(),以及与它们同等的方法。

4 Prefer virtual over interface

当你要声明一个HashMap对象时,你可以声明它为一个HashMap类,或一个Map 类:

Map myMap1 = new HashMap(); HashMap myMap2 = new HashMap();

哪一个更好的呢?

在Pc机编程中,你应该更倾向与声明为Map,因为你可以调用Map中提供的接口来实现更多的功能。但是在手机开发中,通过此种方法的调用,比直接调用方法多花费一倍多的时间。所以,当你用HashMap类,而且它满足自己的需要,就不需要用声明为Map的方法。

5 避免在类内部进行Getters/Setters

在C++语言中,经常使用getters(eg. i=getCount())而不用局部变量的形式(i=mCount).在C++中这是一个很好的习惯,因为编译器可以通过内联进入getters。

但是在Android中,此习惯是不好的,因为调用虚拟机的代价很高,比直接使用局部变量费时的多.所以,在公共的接口中定义getters、setters是可取的,当时,在类中,你应该直接通过局部变量来访问。

如:

for (int i = 0; i < this.getCount();i++)

dumpItem(mItems[i]);

应该写为:

int mCount = this.getCount();

for (int i = 0; i < mCount; i++)

dumpItems(items[i]);

6. 静态成员优于非静态的

在编写程序过程中,因为静态成员的访问不需要构建类的实例。例如,QuyuDAOFactory的getDAO()方法,直接从类进行访问即可。

7 .精确数据计算时,不要使用float或是double类型

使用int或是long进行精确数据计算,自己管理小数位。
当数目不超过9位时,使用int类型;当数目不超过18位时,使用long;如果超过了18位,使用BigDecimal(注意它是对象,不是基本数据类型)。

8. 避免创建重复对象

Strings= new String(“guojun”);//永远不要这么干!
Strongs = “guojun”;//可以接受的改进

9.组合优于继承

当确实需要继承时才采用继承,否则使用类组合来完成。

10.接口优于抽象类

两种机制最明显的区别是抽象类容许包含某些方法的实现,而接口不行。

如:com.zte.resmaster.helpers.AbstractDAOImpl,就是抽象类,它具有得到数据库连接和清除数据库资源的方法,但是怎么实现具体的DAO操作必须是其子类实现。

如果设计成抽象类,一旦子类要求继承其他类时就没有办法实现,因为Java中不能多重继承(extends),但是可以多重实现(implements)。换句话说就是接口是定义混合类型的理想选择。

接口允许非层次类型框架的构造。

接口通过封装类方式,能够获得安全、强大的功能。

当然抽象类有另一个优势:改进抽象类比改进接口更加容易。一旦某个方法的实现发生了变化,仅仅需要更改一个地方;当新加一个方法时,所有子类都具有了该方法。

11. 尽量使用内部类

如果该类仅仅在某个调用者使用,那么把它设计成调用者的内部类。具体的例子,参见:com.zte.resmaster.system.rescomp.dao.RescompDAOOracle。不会暴露该内部类,避免滥用而导致的维护问题。

12. 最小化局部变量的作用域

最小化局部变量最有效的方法是在它第一次使用时声明。

几乎每个局部变量声明都应该包含一个初始值,否则编译也通不过。

方法小而集中,每个方法仅仅处理一种活动。

13. 了解和使用库

Java提供了强大而复杂的类库,在完成某个常用功能之前,看看Java类库中是否已经存在类似功能的类库。一方面减少工作量,一方面使得自己的程序更加简洁高效。

例如:向量(Collection,Set,List…)中字符串的排序:Collections.sort(v);

忽略大小写的排序:Collections.sort(v,String.CASE_INSENSITIVE_ORDER)

还有许多实用类库。

14. 通过接口访问对象

如果存在合适的接口类型,那么参数、返回值、变量和域应该用接口类型声明。

如果没有合适的接口,那么通过类而不是接口访问对象,是完全合适的。

15. 接口优于反射

失去在编译期间进行类型检查提供的好处。

代码笨拙而冗长。

性能损失。反射比正常的方法调用慢40倍左右(JDK1.3)。

有的时候,付出代价是值得的,因为能够得到更多的益处;一般而言,可以通过反射创建一个实例,然后通过他们的接口或是超类正常访问他们。

例如:DAO的Factory设计模式中的通过配置实现数据库实现类的平滑移植。

16. 实现功能后在想如何优化是一个比较好的策略。

17. 遵循普遍接受的命名规则。

18. http用gzip压缩,设置连接超时时间和响应超时时间

http请求按照业务需求,分为是否可以缓存和不可缓存,那么在无网络的环境中,仍然通过缓存的httpresponse浏览部分数据,实现离线阅读。

19. 使用线程池,分为核心线程池和普通线程池,下载图片等耗时任务放置在普通线程池,避免耗时任务阻塞线程池后,导致所有异步任务都必须等待

20. listview 性能优化

  • 1).异步加载图片

item中如果包含有webimage,那么最好异步加载

  • 2).快速滑动时不显示图片

当快速滑动列表时(SCROLL_STATE_FLING),item中的图片或获取需要消耗资源的view,可以不显示出来;而处于其他两种状态(SCROLL_STATE_IDLE 和SCROLL_STATE_TOUCH_SCROLL),则将那些view显示出来

  • 3).复用convertView

在getItemView中,判断convertView是否为空,如果不为空,可复用。如果couvertview中的view需要添加listerner,代码一定要在if(convertView==null){}之外。

  • 4).BaseAdapter避免内存溢出

如果BaseAdapter的实体类有属性非常消耗内存,可以将保存到文件;为提高性能,可以进行缓存,并限制缓存大小。

21.尽量避免static成员变量引用资源耗费过多的实例,比如Context

22.异步任务,分为核心任务和普通任务,只有核心任务中出现的系统级错误才会报错,异步任务的ui操作需要判断原activity是否处于激活状态

23.保证Cursor 占用的内存被及时的释放掉,而不是等待GC来处理。并且 Android明显是倾向于编 程者手动的将Cursor close掉

24.线程也是造成内存泄露的一个重要的源头。线程产生内存泄露的主要原因在于线程 生命周期的不可控

25.使用WeakReference代替强引用,弱引用可以让您保持对对象的引用,同时允许GC在必要时释放对象,回收内存。

对于那些创建便宜但耗费大量内存的对象,即希望保持该对象,又要在应用程序需要时使用,同时希望GC必要时回收时,可以考虑使用弱引用。

26.超级大胖子Bitmap及时的销毁(Activity的onDestroy时将bitmap回收

在被UI组件使用后马上进行回收会抛 RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap)设置一定的采样率(有开发者提供的图片无需进行采样,对于有用户上传或第三方的大小不可控图片,可进行采样减少图片所占的内存),从服务端返回图片,建议同时反馈图片的size巧妙的运用软引用drawable对应resid的资源,bitmap对应其他资源任何类型的图片,如果获取不到(例如文件不存在,或者读取文件时跑OutOfMemory异常),应该有对应的默认图片(默认图片放在在apk中,通过resid获取);

27.Drawable中ui组件需要用到的图片是apk包自带的,那么一律用setImageResource或者setBackgroundResource,而不要根据resourceid

注意:get(getResources(), R.drawable.btn_achievement_normal)该方法通过resid转换为drawable,需要考虑回收的问题,如果drawable是对象私有对象,在对象销毁前是肯定不会释放内存的。

28.复用、回收Activity对象临时的activity及时finish主界面设置为singleTask一般界面设置为singleTop

29.如果ImageView的图片是来自网络,进行异步加载

30.应用开发中自定义View的时候,交互部分,千万不要写成线程不断刷新界面显示,而是根据TouchListener事件主动触发界面的更新

31.在onResume时设置该界面的电源管理,在onPause时取消设置

32.位置信息获取用户的地理位置信息时,在需要获取数据的时候打开GPS,之后及时关闭掉

备注:这里所说的是一些事项,它们不是真理。大家在开发的过程发现自己会了解更多,望大家对该文档能提出批评意见或是补充。

发表在 安卓开发 | 标签为 , , , , , , , , , , | 留下评论

如何提升Android的运行效率?在Android 4.4将用ART运行时替代Dalvik来提升效率

Android开发中存在的效率问题

目前,Android开发过程中普通的程序员拿不到真机测试,无法判断运行效率。一个嵌入式开发程序员可能都知道模拟器和真机的环境差距还是很大的,今天为大家分析一下运行效率。首先我们清楚的是在硬件方面官方已经考虑使用ARM9系列的CPU,工作频率在195MHz到220MHz之间,代表为TI OMAP 850,飞思卡尔等。由于使用了运行效率高的Linux内核,在内存占用和多任务方面还是比较强劲的,但是面临的问题为Java开发API。官方为什么没有像Symbian和Windows Mobile那样提供两种语言开发可能主要是时间问题。未来可能会加入的,不然不像Google的作风。当然真机发布时还有很多周边设备的驱动等问题的编写。
既然使用了运行效率低的Java,程序员就要考虑代码效率了,优化代码是很重要的事情,在Java方面主要用在企业和手机游戏,我们都清楚Java内存分配new后不用自己delete,有GC帮助资源回收。但是Java的异常处理还是和C无法相比,稳定性可能最重要的,毕竟未来的厂商生产时会自己定制GPhone硬件,造成运行兼容性等问题。Java的跨平台越来越差了,目前冒出的Dalvik会如何呢?尽管Sun CEO表示希望Android和JME兼容但从目前的代码中看很多都是重复的图形库居多。
程序员抵制的主要是优化代码运行,如分配局部临时变量时的位置、在算法方面少用递归,线程同步等问题。

在Android 4.4将用ART运行时替代Dalvik来提升效率

Android操作系统已逐渐成熟,谷歌开始将注意力转向一些底层组件,其中之一是负责应用程序运行的Dalvik运行时,谷歌已经花了两年时间开发更快执行效率更高、更省电的ART运行时。可能你还没有意识到,新的ART运行时是Android 4.4系统最大的一次革新。

 

ART是“Android Runtime”的缩写,顾名思义,它是安卓系统赖以生存的底层运行环境。

在过去,安卓的底层代码由Dalvik Java虚拟机运行,Dalvik依靠一个Just-In-Time(JIT)编译器去向硬件“解释”App字节码,代码和硬件打交道时平白无故多出一个解释过程,这一机制并不高效,被看作安卓运行效率低下的“毒瘤”。不过,Dalvik虚拟机让应用能更容易在不同硬件和架构上运行,是安卓系统普及的功臣。

 

而新的ART则完全改变了这套做法,其处理应用程序执行的方式完全不同于Dalvik,在应用安装时,ART就直接把代码预编译成机器语言,这一机制叫Ahead-Of-Time (AOT)编译。和Dalvik相比,经过ART编译后的应用从根本上省略了解释字节码这个过程,运行起来更有效率、耗电更少、占的内存也更低。

当然,预编译也带来了两个问题,一个是应用占用的存储空间将会更大,另一个是这个过程也会让应用安装耗时更长。预编译的App体积至少会大20%,安装时间则要看App本身的复杂程度。不过,App的安装过程只有一次,相信大部分人是能忍受这个时间的。

实际上,谷歌早在Android 4.2的时候就已经开展了新运行环境“ART”的测试,现在ART运行环境已经在Android 4.4中开放测试了,用户可以在开发者选项中找到“Select runtime”,然后选择“Use ART”并重启即可。

开发实例FAQ:

:现在实现一个在线实时的视频监控,实时接收网络H264数据,然后解码显示,显示的时候是用ImageView来显示的,但是发现当全屏显示时,会耗费较大的时间,导致显示延时。 我解码出来的是320*240的图片,然后显示的时候是用imageView.setImageBitmap(bitmap),在布局文件中我设置长宽fill_parent,我手机是800*480的,系统在绘制时会自动进行拉升,定位后发现耗费的时间出现在此处。 请问有没有其他的办法可以提升效率绘制图片的,例如windows mobile有directshow,或者能否使用opengl来绘制,我看做3D游戏赛车是全屏的,效率还不错。

:1.解码的时候就解成你屏幕大小的; 2,用surfaceview来完成

发表在 安卓开发 | 标签为 , , , , , | 留下评论

win8平板笔记本电脑是不是能装PC的软件?

1. WIN8系统的开发背景-为什么微软要开发windows8

首先需要弄清楚,其实对于系统和程序来说,平板还是PC并无不同,只是形状而已,所不同的是CPU,因为CPU不同,指令不同,程序就必须重新编译才能运行,windows 不同于Linux,一般不提供源代码,而Linux因为有源代码,所以软件基本都是跨平台。但是因为平板及手持设备ARM CPU占据着绝对性的份额(根据2012报告显示:ARM在手机芯片市场的份额超过90%),所以说手持或手机设备,基本都是ARM内核的cpu,

windows系统在桌面PC上占据着绝对性的份额,所以 压根就没有考虑CPU问题,但是现在ARM+安卓开始蚕食Intel和微软的市场,Win8的跨界出现就是为了抢占安卓所占据的市场,借助这个突破口进入手持设备市场。

 

2. WIN8平板笔记本电脑是不是能装PC的软件?

所以可以这么理解:x86平板就是个PC,只不过是触摸的。

ARM平板不能运行所有x86、x64本地代码的软件,但可以支持那些本身跨平台运行的代码,如.NET、Java的开发的应用程序。

简单的说x86版可以装PC上的软件,ARM版需要用新的Metro方式开发的软件才可以。

 

3. 如何选择Win8 平板笔记本电脑?

 

X86版的就OK了,不过价格要贵一些,而且续航肯定不如ARM版的。

 

4. 怎么区分x86版还是ARM版:

如果CPU是Intel的,那就是x86的,ARM则直接标注ARM xxx。

发表在 windows驱动开发 | 标签为 , , , , | 留下评论

VirtualBox安装ghost XP系统的时候蓝屏显示p3.sys错误

因为公司内网的关系,准备安装个Virtualbox虚拟机用来直接通过3G上网modem联网,在WIN7下安装VirtualBOX 4.2.12,装一个Ghost版xp sp3用来安装XAMPP作为测试用web服务器,但是ghost完以后,启动系统的时候蓝屏显示p3.sys错误。到网上找了一下,应该是跟虚拟机有关的问题。

解决方法是:在ghost完以后,在WINPE中把系统盘下的windows\system32\drivers下面的p3.sys删了,然后再重启,又提示lsass.exe – 操作失败。暂时没找到解决方法,奇怪以前用旧版VirtualBox没有碰到该问题。

看来还是安装wdlinux,晚上回去拷一份过来,公司网络太慢了。

发表在 Linux驱动开发 | 标签为 , | 留下评论

WDM驱动程序的基本结构和实例-《Windows内核编程》

WDM驱动的基本结构分以下几部分进行阐述:

对于WDM驱动程序来说,一般都是基于分层的,即完成一个设备的操作,至少要由两个驱动设备共同完成。WDM驱动模型是建立在NT式驱动程序模型基础之上的。

 

1)物理设备对象和功能设备对象

物理设备对象(Physical Device Object,PDO)和功能设备对象(Function Device Object,FDO)的关系是“附加”与“被附加”的关系。

当PC插入某个设备时,PDO会自动创建。确切的说,是由总线驱动创建的。PDO不能单独操作设备,需要配合FDO一起使用。系统会提示检测到新设备,要求安装驱动程序。需要安装的驱动程序就是WDM程序,此驱动程序负责创建FDO,并且附加到PDO上。

当一个FDO附加到PDO上时,PDO设备对象的子域AttachedDevice会记录FDO的位置。PDO被称作底层驱动或下层驱动,而FDO被称作高层驱动或上层驱动。

复杂一点的情况是,在FDO和PDO之间还会存在过滤驱动。在FDO上面的过滤驱动被称作上层过滤驱动,在FDO下层的驱动被称作下层过滤驱动。每个设备对象中,有个StackSize子域,表明操作这个设备对象需要几层才能到达最下层的物理设备。

过滤驱动可以嵌套,即可以有很多个高层过滤驱动或多个底层过滤驱动。过滤驱动不是必须的,在WDM模型中PDO和FDO是必须的。

 

NT设备是被动装入的,例如当有设备插入PC时,系统不会有提示,用户需要自己指定加载何种驱动;而WDM驱动则不然,当插入设备时,系统会自动创建出PDO,并提示请求用户安装FDO。

 

2)WDM驱动的入口程序

和NT驱动一样也是DriverEntry,但是初始化作用被分散到其他例程中。如创建设备对象的工作被放在了AddService例程中,同时,在DriverEntry中,需要设置对IRP_MJ_PNP处理的派遣函数。

WDM驱动的DriverEntry和NT式驱动的DriverEntry有以下几点不同:

(1)增加了对AddService函数的设置;AddService例程负责创建FDO,并附加到PDO上。

(2)创建设备对象的操作不在这个函数中了,而转到了AddService例程中。

(3)必须加入IRP_MJ_PNP的派遣回调函数。IRP_MJ_PNP主要是负责计算机中即插即用的处理。

 

3)WDM驱动的AddService例程

AddService例程是WDM独有的。在DriverEntry中需设置AddService例程的函数地址,设置的方式是驱动对象中有个DriverExtension子域,DriverExtension中有个AddService子域,将该子域指向AddService例程的函数地址即可。

和DriverEntry不同,AddService例程的名字可以任意命名:

DRIVER_ADD_DEVICE AddDevice;

 

NTSTATUS AddDevice(

__in  struct _DRIVER_OBJECT *DriverObject, //驱动对象(I/O管理器创建的)

__in  struct _DEVICE_OBJECT *PhysicalDeviceObject //设备对象(底层总线驱动创建的PDO设备对象)

//传入该参数的目的是将FDO附加在PDO上

)

{ … }

AddService函数的功能可分为:

(1)通过IoCreateDevice等函数,创建设备对象,该设备对象就是FDO。

(2)创建FDO后,需要将FDO的地址保存下来,保存的位置是在设备扩展中。

(3)驱动程序将创建的FDO附加到PDO上,附加这个动作是利用函数IoAttachDeviceToDeviceStack实现的:

PDEVICE_OBJECT IoAttachDeviceToDeviceStack(

__in  PDEVICE_OBJECT SourceDevice, //要附加到其他设备上的设备,

//将FDO附加在PDO之上时,此处即填FDO的地址

__in  PDEVICE_OBJECT TargetDevice //被附加的设备,将FDO直接附加在PDO上时

//(不考虑过滤驱动),此处即时PDO的地址

);

返回值:附加后,返回附加设备的下层设备。如果中间没有过滤驱动,返回值就是PDO;如果中间有过滤驱动,返回的是过滤驱动。

当FDO附加到PDO上时,PDO会通过AttachedDevice子域知道它上层的设备是FDO(或过滤驱动);而FDO无法知道下层是什么设备,因此,需要通过设备扩展设置FDO下层的设备,例如:

//设备扩展结构体

typedefstruct _DEVICE_EXTENSION

{

PDEVICE_OBJECT fdo; //功能设备对象FDO

PDEVICE_OBJECT NextStackDevice; //FDO的下层驱动设备

UNICODE_STRING ustrDeviceName; //设备名

UNICODE_STRING ustrSymLinkName; //符号链接

}DEVICE_EXTENSION, *PDEVICE_EXTENSION;

一般根据自己的需要定制自己的设备扩展。子域fdo是为了保存FDO的地址以备后用;子域NextStackDevice是为了定位设备的下一层设备。在附加操作完成后,需要设定符号链接,以便用户应用程序访问该设备。

 

4)DriverUnload例程

在NT式驱动中,DriverUnload例程主要负责做删除设备和取消符号链接。而在WDM驱动中,这部分操作被IRP_MN_REMOVE_DEVICE的处理函数所负责。因此,如果在DriverEntry中有申请内存的操作,可以在DriverUnload例程中回收这些内存,DriverUnload例程变得相对简单了。

 

5)对IRP_MN_REMOVE_DEVICE IRP的处理

驱动程序内部是由IRP驱动的。创建IRP的原因很多,IRP_MN_REMOVE_DEVICE这个IRP是当设备被卸载时,由即插即用管理器创建,并发送到驱动程序中的。IRP一般由两个号码指定该IRP的具体意义:一是主IRP号(Major IRP);一是辅IRP号(Minor IRP)。

每个IRP都由对应的派遣函数所处理,派遣函数是在DriverEntry中指定的。

在WDM驱动程序中,对设备的卸载一般是在对IRP_MN_REMOVE_DEVICE的处理函数中进行的。除了需要删除设备,取消符号链接外,在卸载函数中还需要将FDO从PDO上的堆栈中移除掉,使用函数IoDetachDevice:

VOID IoDetachDevice(

__inout  PDEVICE_OBJECT TargetDevice //下层堆栈上的设备对象

);

调用此函数后,可将FDO从设备链上删除,但PDO还是存在的,PDO的删除是由操作系统负责的。

 

目前开发WDM 驱动程序的方法有三种:

 

①使用 Microsoft 的 Windows DDK/WDK 工具开发。

②使用 KRFTech 公司的 WinDriver 。

③使用 NuMega 公司的 DriverStudio 。

发表在 windows驱动开发 | 标签为 | 留下评论

驱动开发工具之:C++程序风格的思考

C++自从诞生后,在底层开发领域,一副前无古人,后无来者的王者风范,上接天,下接地气,绵绵不绝!

C++像一把魔幻刀,你心里有什么,它就是什么型,随心所现。 所以它很强大,但强大的同时也意味着复杂。C++因为本身支持多种范型设计(面向过程, 基于对象,面向对象,普通泛型,模板元编程等), 使得C++的程序风格和其他语言相比更加多种多样。其他语言,比如Java/C#只支持面向对象,所以他们的风格很统一, 无论是框架标准库还是应用,都是以对象,接口和模式为主导。 但是C++程序就不一样了, 可以说C++程序风格没有固定的标准, 每个人根据他的经历和使用的框架,会有完全不一样的风格, 下面是程序界C++猿们常现的一些C++程序风格:


1. 经典C++流:类是核心,例程多用C Runtime的,很少用模版,一般是正统教育的结果。
2. 古典C流:基本上当C用,偶尔用用对象,不使用异常,喜欢怀旧。
3. MFC流:秉承MFC的风格,主要使用MFC/ATL对象和Win32 API,不喜欢STL,用很多的宏把IDE的语法提示模块折磨到崩溃。
4. Portable流:以C Runtime和STL为主要工具,使用类和模版,不跨平台毋宁死。
5. Functional流:以模版和STL为主要武器,大量使用函数式语言的设计方法,并号称这才是真正的C++。
6. Win32流:多使用全局函数,偏爱Win32 API,但不排斥C Runtime,通常喜欢轻量级的程序,所以身材也比较苗条。
7. Java流:全面使用Java的风格,不能容许任何全局成员,但允许使用STL的集合类,写很多叫Factory的类。
8. COM流:喜欢AddRef()和Release(),大量使用接口,隐藏一切可以隐藏的东西,诵经的时候要把上帝替换成COM。
9. 戒律流:追求完美的C++程序,计较每一个const和throw(),极力避免不安全的cast,随身一定要带一本ISO C++手册。
10. 混沌流:其程序无常形,无恒道,变幻莫测,吾不知其名。 

上面确实总结了我们常见的一些C++程序风格,相信大部分C++程序员都可以再里面找到自己曾经或现在的影子。另外每个人C++程序风格不是一成不变的,随着他的项目经历会不断的变化。比如一般人刚毕业时的风格都是带类的C,代码风格偏向面向过程; 后来随着对面向对象的深入, 慢慢地会使用模式和接口来设计,此时代码风格偏向面向对象;  再后面可能会深入STL和泛型,甚至模板元编程, 此时代码风格使用模板泛型; 最后有些人可能会觉得过度的关注面向对象的设计模式和模板的泛型设计, 会让人偏离对要解决的问题本身的关注, 最后他的风格又回到了原始的C或是刚毕业时带类的C的风格。

从上面可以看到,我们很难给C++程序风格定出一个比较统一的标准,但是我想我们可以根据我们要解决的问题不同而使用不同的风格。下面是我个人的一些看法:


(1)C++底层语言基础库(STL, Boost)以泛型为主导, 以高效和通用为设计原则, 这方面我想大家已经达成共识

(2)C++应用基础库和框架以面向对象和泛型为主导。基础框架一般对扩展性和性能都有一定要求,对于框架一般我们是大量实践经验的总结,所以我们基本上已经知道它的所有可变情况, 所以理论上我们可以进行精致的设计,然后通过模板参数的Traits和Policy来分离所有可能的情况,框架本身也有一定的复杂性,需要面向对象来封装和解耦, ATL是这方面作为COM组件开发基础库的成功例子。基础框架以高效,专用和扩展性为设计原则。

(3)C++应用层以面向对象为主导。应用层逻辑是多变的, 理论上你也可以采用模板参数的方式来应对变化, 但是应用层的变化非常复杂, 很多事不可预测的, 所以你不可能以模板参数的方式预测到所有可能的情况。另外C++现在还没有对泛型Concepts的描述机制, 导致模板代码比较难懂。在多变的应用层大量采用模板显然不是一个好的选择。 另外模板在应用层的大量使用也没有比较成熟的经验, 而面向对象和模式已经是非常成熟。应用层以低耦合,灵活应对变化为设计原则。

(4)C++模块(DLL)间的交互则以C方式API或是仿COM(Interface+Factory)为主导, 模块接口和交互以简洁和二进制兼容为设计原则。

总之, 我们应该灵活应用C++各种风格和范型的特点, 采用 ”多范型“ 程序设计的思路来解决问题, 而不是采用单一风格。

C++相较于C所增加的更多特性都是为增加通用性和可扩展性关系,越往操作系统底层,离这些抽象的东西就越远, 也就不需要所谓的模式和模板了,  所以Linux之父才会给C++差评。

演绎自:Cppblog

发表在 Linux驱动开发 | 标签为 , | 留下评论

Windows系统内核注入DLL的实现及思路

Windows系统内核注入,技术古老但很实用。现在部分RK趋向无进程,玩的是SYS+DLL,有的无文件,全部存在于内存中。可能有部分人会说:“都进内核了.什么不能干?”。是啊,要是内核中可以做包括R3上所有能做的事,软件开发商们也没必要做应用程序了。有时,我们确实需要R3程序去干驱动做起来很困难或者没必要驱动中去做的事,进程 /   DLL是不错的选择,但进程目标太大,所以更多的同学趋向于注DLL。

若要开发安全软件、小型工具,可借鉴其思路,Anti Rootkits时,在某些极端情况下,可使用同样的技术发现、清除RK,保证用户电脑的正常使用。在此,我将探讨几种内核注入DLL的思路及实现原理。

(1) APC技术

给一个Alertbale的用户态线程插APC,让其执行其中的ShellCode,来执行我们的代码。这个方法简单易行,但是不够稳定,兼容性不好。测试中发现经常出现Explorer.exe等插崩溃的情况,而且有杀软在的情况下,插入有时会被拦截,起不到应有的效果。(可参考我以前逆过的一个驱动:逆向fuck.sys–编译通过–源码)

(2)Windows系统 内核Patch   CreateThread

是系统加载时对象管理器加载最新磁盘DLL到内存的,当其他进程想调用某个DLL时,就不用重复从磁盘加载了,而会从这里映射一份到自己的进程空间中去。这样给我们做全局Patch提供了一个很好的机会:
ZwOpenSection打开 ,调用ZwMapViewOfSection映射一份到自己进程空间,然后寻找kernel32.dll在内存中代码节的空隙,选择这里作为我们fake函数的存储Buffer。修改CreateThread函数的开头5字节跳转到这个间隙,当系统任何一个线程创建时,会走到CreateThread函数,然后执行空隙中的ShellCode,其负责调用LoadLibrary加载我们的DLL。DLL一经加载,会发IOCTL通知本驱动,让驱动卸载HOOK。这样就完成了内核注DLL的过程。测试时发现Svchost.exe进程调用CreateThread函数很频繁,所以触发也会很快,基本1秒不到就能将DLL加载进去,而我们的HOOK也卸掉了。所以稳定性提高不少。示意图如下:
e208bddc96b97ebacc11666eb7b52038e16e553896ddd86f

(3) Windows系统内核 HOOK ZwMapViewOfSection

有部分模块加载时会调用ZwMapViewOfSection,比如进程创建时映射N份DLL到自己的虚拟空间中去.我们替换SSDT中的这个函数,过滤出是加载Kernel32.dll的情况,从参数中取得其基址,Inline Hook其EAT中的CreateThread函数,跳转到在这个进程虚拟地址空间中申请的Buffer,在其中完成DLL的加载过程.

关键API:
ZwAllocateVirtualMemory —- 在此进程空间中分配内存,存放Shellcode
ZwProtectVirtualMemory —- 使当前内存块具有可读可写属性
IoAllocateMdl —- 创建MDL

关键Code如下:
215571a87f6449aaca130c68fae3627f0594c31329388a69

同方法2相比,原理类似。但修改时机不同,效果差不多,只是注入DLL的时间会慢一些。至于Shellcode的编写,就大同小异了.萝卜白菜各有所爱,主要看个人发挥。要是闲写shellcode麻烦,请到看雪学院去查资料,模板很多,在这里就不YY了。
【看雪读书月】学习ShellCode编写
[note]一个简单的Shellcode
shellcode之小小琢磨
Add_Section

(4) Windows系统内核 HOOKNtCreateThread

跟踪进程创建的流程,会很明晰的发现有多点可以patch来实现DLL的注入。

进程创建完时是一个空水壶,里面没有沸腾的热水(threads),于是系统调用NtCreateThread创建其主线程(给空水壶注水 – 凉水),在这个暂停的线程里面折腾了一阵后完事了也厌倦了,于是系统跳了出来,回到进程空间中,调用Kernel32.dll去通知CSRSS.EXE,对它说:“这里有一个新进程出生了,你在你的表里标记一下”。然后就开始加载DLL啦,把系统KnownDLLs中的自己需要的DLL都Map一份到这个大水壶中。接着KiThreadStartup加热水壶中的凉水,于是水就开始沸腾了,此时主线程开始工作。。。

拦截NtCreateThread,取得当前线程上下文,保存它要返回的地址(会回到空水壶中去),劫持为我们自己分配的地址,在其中填充ShellCode来加载目的DLL。至于选择Buffer,思路很多。这里可简单的Attach到当前进程,在充足的虚拟2GB进程地址空间中分配属于你自己的一块小内存,够放ShellCode足矣。示意图如下:
13335895afc7c6137af4806a

                  (5) 内核感染常用模块,让感染模块帮我们Load DLL
这个方法就有点绕远了,开始了最本质最原始的感染,可增加新节,可插空隙,总之,让别人的模块Load进内存时顺路的帮我们加载下DLL,DLL一旦加载就可以恢复感染,清除痕迹。至于感染代码,网上一堆。只要不是驱动感染驱动(多了个校验和),其他性质都一样,看自己发挥啦。

          (6) 拦截NtCreateUserProcessNtCreateSymbolicLinkObject

前者在Vista下才有. 拦截后通过PsLookupProcessThreadByCid得到ETHREAD / EPROCESS,判断是否是CSRSS.EXE引起的,若是则在此进程空间内分配一块内存,调用NtGetContextThread得到当前的线程上下文,调用ZwWriteVirtualMemory填充Shellcode区域,取得LdrUnloadDllLdrGetDllHandle等函数地址,通过他们加载DLL。然后调用NtSetContextThread恢复原始的Context。关于这种方法,可参考DriverDevelop上某人发的BIN。
[”内核实现DLL注入.可以完美绕过KAV瑞星等杀毒软件”]

(7) Windows系统内核拦截NtResumeThread
(8)NtUserSetWindowsHookEx 注入

顺便提下R3上DLL的注入:
1.CreateRemoteThread (or NtCreateThreadEx (Used in Vista))
2.SetThreadContext (change the EIP)
3.NtQueueAPCThread
4.RtlCreateUserThread
5. SetWindowHookEx

Windows系统内核注入小结:

纵观进程启动的全过程,可patch的地方很多,只要保证进程、线程上下文不被破坏,注入的手法可多种多样。只要保证我们的DLL注入时间足够短,稳定性足够高即可。当我们迫不得已要从内核注入DLL到用户进程去时,系统已经中毒很深,此时运用类似上面提到的技术来加载DLL,让DLL做我们驱动无法完成的任务,是可以接受的。

上面提到的思路是我暂时想到并且已经实现了的,详细过程可参见代码。欢迎积极探讨更好更稳定而且不邪恶的方法。

———————————————————————————–
参考资料:
1.       Windows Internals—Processes,Threads,Jobs
2.       漫谈兼容内核系列:WINDOWS进程的用户空间
3.       WRK 1.2 ,windbg

 

Author :   sudami   [sudami # 163.com]
Time   :   01-11-2008
Links   :  http://hi.baidu.com/sudami

发表在 windows驱动开发 | 标签为 , | 留下评论

WIN7 + Visual Studio 2010 编译Windows驱动程序

驱动程序开发环境:Win7 + VS2010

目标平台:XPE

DDK/WDK安装在D:\WINDDK

 

一.用VS2010创建一个“空项目”:

(“Visual C++” -> “常规” -> “空项目”)

二.将编写好的源代码文件导入项目中

三.修改VS2010的IDE 设置,添加支持驱动程序编译链接的头文件和库文件

在Include目录中添加:

  • D:\WinDDK\7600.16385.1\inc\wxp
  • D:\WINDDK\7600.16385.1\inc\crt (可选)
  • D:\WINDDK\7600.16385.1\inc\ddk\wxp
  • D:\WINDDK\7600.16385.1\inc\ddk\wdm\wxp

在Lib目录中添加:

D:\WINDDK\7600.16385.1\lib\wxp\i386

 

四.修改项目属性。

将驱动程序项目属性依次修改为:

1. “配置属性”->“C/C++” -> “常规”:

  • 调试信息格式:C7 兼容(/Z7)

3. “配置属性”->“C/C++” -> “预处理器”:

  •  预处理器定义:WIN32=100;_X86_=1;WINVER=0x501;DBG=1
    ( WINVER = 驱动运行的Windows版本: 0x500 = win2000 , 0x501 = winxp 0x502 = win2003, _X86_ 表示 32位系统,_AMD64_ 表示64位系统 ,_IA64_ 表示intel 安腾 64位系统,DBG=1 表示创建调试版本的驱动 )
    ( 编译Win 2000的NDIS驱动时增加:BINARY_COMPATIBLE=0;NDIS40_MINIPORT=1;NDIS40=1;NDIS_MINIPORT_DRIVER=1 )
    ( 编译Windows XP,2003的NDIS驱动时增加:BINARY_COMPATIBLE=0;NDIS51_MINIPORT=1;NDIS51=1;NDIS_MINIPORT_DRIVER=1 )
    ( 如果项目有 source 文件,那么该文件的 C_DEFINES 字段会说明此项目编译时需要预定义的标识符 )
    ( 有时候有些问题,比如未声明的标识符,或者标识符的类型不对,或者结构没有成员之类的问题,这时需要看具体源码中的一些定义是不是被条件编译指令 #if 屏蔽,如果是,增加一些定义项目再尝试编译 )

忽略标准包含路径:

  • 是 ( 设置为此值时,必须加入项目需要的所有头文件所在的目录,参看第三步的内容,这样项目就不会依赖IDE环境的设置 )
  • 否 ( 设置为此值时,将依赖 IDE 的环境的相关设置 )

4. “配置属性”->“C/C++” -> “代码生成”:

  • 启用最小重新生成:否
  • 基本运行时检查:默认值
  • 运行时库:多线程调试(/MTd) 或 多线程(/MT)
  • 缓冲区安全检查:否 (可避免出现 LINK : error LNK2001: 无法解析外部符号 __security_cookie)

5.“配置属性”->“C/C++” -> “高级”:

  • 调用约定:__stdcall (/Gz)

6. “配置属性”->“链接器” -> “常规”:

  • 输出文件:$(OutDir)\$(ProjectName).sys
  • 启用增量链接:否(/INCREMENTAL:NO)
  • 忽略导入库:

是 ( 设置为此值时,必须在附加库目录中加:D:\WINDDK\3790.1830\lib\wxp\i386 ,这样项目就不会依赖IDE环境的设置 )
否 ( 设置为此值时,将依赖 IDE 的环境的相关设置 )

7. “配置属性”->“链接器” -> “输入”:

附加依赖项:ntoskrnl.lib Hal.lib wdm.lib wdmsec.lib wmilib.lib ndis.lib MSVCRT.LIB LIBCMT.LIB
( HalXXX函数在Hal.lib,WmiXXX函数在 wmilib.lib ,NdisXXX函数在 ndis.lib )
( 必要时需要增加微软的标准库 MSVCRT.LIB MSVCRTD.LIB(调试库) LIBCMT.LIB LIBCMTD.LIB(调试库) )
( 如果源码中有 source 文件,那么该文件的 TARGETLIBS 字段会列出该项目需要的库 )

忽略所有默认库:是(/NODEFAULTLIB)

8.“配置属性”->“链接器” -> “清单文件”:

启用用户帐号控制UAC:否

9. “配置属性”->“链接器” -> “调试”:

生成映像文件:是(/MAP)

映像文件名:$(TargetDir)$(TargetName).map

10. “配置属性”->“链接器” -> “系统”:

堆栈保留大小:4194304

堆栈提交大小:4096

驱动程序:驱动程序(/DRIVER)

11. “配置属性”->“链接器” -> “高级”:

入口点:DriverEntry

设置效应和:是(/RELEASE)

基址:0x10000

随机基址:默认值

数据执行保护(DEP):默认值

 

12. “配置属性”->“链接器” -> “命令行”->“附加选项”:

添加开关:/SECTION:INIT,D /IGNORE:4078 /safeseh:no
可以避免以下错误提示
LINK : warning LNK4078: 找到多个“INIT”节,它们具有不同的属性(E2000020)
LINK : error LNK2001: 无法解析的外部符号__load_config_used

 

五.XP驱动程序编译,链接,安装。

本人按照以上设置成功编译链接 Windows XP,并安装成功

一些要修改DDK例子源码方能成功的问题,目前不知道什么选项可以不改:
源码中的关键字 try 要改为 __try , except 要改为 __except .

 

整理自: http://lion3875.blog.51cto.com/2911026/595208

发表在 windows驱动开发 | 标签为 , , | 留下评论

usb技术特点-USB驱动开发基础

一.USB基础知识

USB是英文Universal Serial Bus的缩写,中文含义是“通用串行总线”。1994年,Intel、Compaq、Digital、IBM、Microsoft、NEC、Northern Telecom等七家世界著名的计算机和通讯公司成立了USB论坛,花了近两年的时间形成了统一的意见,于1995年11月正式制定了USB0.9通用串行总线(Universal Serial Bus)规范,1997年开始有真正符合USB技术标准的外设出现。USB1.1是目前推出的在支持 USB的计算机与外设上普遍采用的标准。1999年初在Intel的开发者论坛大会上,与会者介绍了 USB2.0规范,该规范的支持者除了原有的Compaq、Intel、Microsoft和NEC四个成员外,还有惠普、朗讯和飞利浦三个新成员。USB2.0向下兼容USB1.1,数据的传输率将达到120Mbps~ 240Mbps,还支持宽带宽数字摄像设备及下一代扫描仪、打印机及存储设备。

目前普遍采用的USB1.1主要应用在中低速外部设备上,它提供的传输速度有低速1.5Mbps和全速 12Mbps两种,低速的USB带宽(1.5Mbps)支持低速设备,例如显示器、 调制解调器、键盘、鼠标、扫描仪、打印机、光驱、磁带机、软驱等。全速的USB带宽(12Mbps)将支持大范围的多媒体设备。

USB之所以能得到广泛支持和快速普及,是因为它具备下列的很多特点:

1.终端用户的易用性

●为接缆和连接头提供了单一模型

●电气特性与用户无关

●自检外设,自动的进行设备驱动和设置

●外设可以动态连接,动态重置

2.广泛的适用性

●适应不同设备,传输速率从几kb/s到十几Mb/s

●在同一线上支持同步、异步两种传输模式

●支持对多个设备的同时操作

●可同时操作127个物理设备

●在主机和设备之间可以传输多个数据和信息流

●支持多功能的设备

●利用底层协议,提高了总线利用率

3.同步传输带宽

●确定的带宽和低延迟适合电话系统和音频的应用

●同步工作可以利用整个总线带宽

4.灵活性

●直接发送一系列指定大小的数据包,允许对设备缓冲器大小进行选择

●通过指定数据缓冲区的大小和执行时间,支持各种数据传输率

●通过协议对数据流进行缓冲处理

5.健壮性

●在协议中使用差错处理/差错恢复机制

●完全实时热插拔

●可以对有缺陷的设备进行鉴别

6.与PC产业的一致性

●协议的易实现性和完整性

●与PC机的即插即用体系结构一致

●与现存操作系统有良好衔接的接口

7.性价比

●以低廉的价格提供传输速率为1.5Mb/s的子通道

●将外设和主机硬件进行了最优化的集成

●促进了低价格外设的发展

●廉价的电缆和连接头

●运用商业技术降低成本

8.可升级性

●体系结构的可升级性支持在一个系统中同时存在多个USB主机控制器

标签为 , , , | 留下评论