-
2019-04-11 22:39:21
一、两种分类:
1、观察者模式:java自带观察者模式类,可直接实现,一个事件源发生事件 触发对 应观察者
2、订阅发布模式:订阅端 事件通道 发布端 解耦度高,优选二、三种实现
1、spring框架实现 自带了事件监听的相关类,是对java jdk的监听事件的优化
2、zookeper 实现配置文件的热部署,配置在节点中存贮 ,在java中添加zookeper相关watcher代码,利用zookerper带有的watcher来监听节点的变化,从而在java项目中对配置进行不停机更新
3、消息中间件,主要用于微服务之间的通信和解耦,适用于同一项目下有较多服务的情况更多相关内容 -
【C/C++服务器开发】事件驱动、事件驱动架构、事件驱动编程及设计模式
2021-12-03 22:28:06文章目录一、事件驱动二、事件驱动编程事件驱动和异步IO看图说话讲事件驱动模型三、C/C++实现事件驱动四、常用的C/C++事件驱动库 一、事件驱动 首先我们来看看百度百科的介绍。 所谓事件驱动,简单地说就是你点什么...一、事件驱动
首先我们来看看百度百科的介绍。
所谓事件驱动,简单地说就是你点什么按钮(即产生什么事件),电脑执行什么操作(即调用什么函数).当然事件不仅限于用户的操作. 事件驱动的核心自然是事件。从事件角度说,事件驱动程序的基本结构是由一个事件收集器、一个事件发送器和一个事件处理器组成。事件收集器专门负责收集所有事件,包括来自用户的(如鼠标、键盘事件等)、来自硬件的(如时钟事件等)和来自软件的(如操作系统、应用程序本身等)。事件发送器负责将收集器收集到的事件分发到目标对象中。事件处理器做具体的事件响应工作,它往往要到实现阶段才完全确定,因而需要运用虚函数机制(函数名往往取为类似于HandleMsg的一个名字)。对于框架的使用者来说,他们能够看到的是事件处理器。这也是他们所关心的内容。
视图(即我们通常所说的“窗口”)是“事件驱动”应用程序的另一个要元。它是我们所说的事件发送器的目标对象。视图接受事件并能够对其进行处理。当我们将事件发送到具体的视图时,实际上我们完成了一个根本性的变化:从传统的流线型程序结构到事件触发方式的转变。这样应用程序具备相当的柔性,可以应付种种离散的、随机的事件。
由于Windows本身是基于“事件驱动”模型的。因而在Windows操作系统下实现应用程序框架有相当的便利。在事件驱动程序的基本单元中,事件收集器已经由Windows系统完成;事件发送器也已经由Windows完成了部分内容。之所以是部分而非完全是因为Windows是用C语言实现的,而不是C++。由于没有对象,Windows将事件发送到所谓的“窗口函数”中(尽管不是发送到具体的对象,但应该说这是面向对象方式实现的一个变体)。要感谢Windows做了这件事。确定事件的目标所要做的工作的复杂可能要超出我们的想象。
可以看到对于事件驱动来说,最重要的是一个事件收集器、一个事件发送器和一个事件处理器。
二、事件驱动编程
事件驱动和异步IO
通常,我们写服务器处理模型的程序时,有以下几种模型:
(1)每收到一个请求,创建一个新的进程,来处理该请求;
(2)每收到一个请求,创建一个新的线程,来处理该请求;
(3)每收到一个请求,放入一个事件列表,让主进程通过非阻塞I/O方式来处理请求
上面的几种方式,各有千秋,
第(1)中方法,由于创建新的进程的开销比较大,所以,会导致服务器性能比较差,但实现比较简单。
第(2)种方式,由于要涉及到线程的同步,有可能会面临死锁等问题。
第(3)种方式,在写应用程序代码时,逻辑比前面两种都复杂。
综合考虑各方面因素,一般普遍认为第(3)种方式是大多数网络服务器采用的方式看图说话讲事件驱动模型
在UI编程中,常常要对鼠标点击进行相应,首先如何获得鼠标点击呢?
方式一:创建一个线程,该线程一直循环检测是否有鼠标点击,那么这个方式有以下几个缺点:在UI编程中,常常要对鼠标点击进行相应,首先如何获得鼠标点击呢?
方式一:创建一个线程,该线程一直循环检测是否有鼠标点击,那么这个方式有以下几个缺点:-
CPU资源浪费,可能鼠标点击的频率非常小,但是扫描线程还是会一直循环检测,这会造成很多的CPU资源浪费;如果扫描鼠标点击的接口是阻塞的呢?
-
如果是堵塞的,又会出现下面这样的问题,如果我们不但要扫描鼠标点击,还要扫描键盘是否按下,由于扫描鼠标时被堵塞了,那么可能永远不会去扫描键盘;
-
如果一个循环需要扫描的设备非常多,这又会引来响应时间的问题;
所以,该方式是非常不好的。
方式二:就是事件驱动模型
目前大部分的UI编程都是事件驱动模型,如很多UI平台都会提供onClick()事件,这个事件就代表鼠标按下事件。事件驱动模型大体思路如下:-
有一个事件(消息)队列;
-
鼠标按下时,往这个队列中增加一个点击事件(消息);
-
有个循环,不断从队列取出事件,根据不同的事件,调用不同的函数,如onClick()、onKeyDown()等;
-
事件(消息)一般都各自保存各自的处理函数指针,这样,每个消息都有独立的处理函数;
事件驱动编程是一种编程范式,这里程序的执行流由外部事件来决定。它的特点是包含一个事件循环,当外部事件发生时使用回调机制来触发相应的处理。另外两种常见的编程范式是(单线程)同步以及多线程编程。让我们用例子来比较和对比一下单线程、多线程以及事件驱动编程模型。下图展示了随着时间的推移,这三种模式下程序所做的工作。这个程序有3个任务需要完成,每个任务都在等待I/O操作时阻塞自身。阻塞在I/O操作上所花费的时间已经用灰色框标示出来了。
在单线程同步模型中,任务按照顺序执行。如果某个任务因为I/O而阻塞,其他所有的任务都必须等待,直到它完成之后它们才能依次执行。这种明确的执行顺序和串行化处理的行为是很容易推断得出的。如果任务之间并没有互相依赖的关系,但仍然需要互相等待的话这就使得程序不必要的降低了运行速度。
在多线程版本中,这3个任务分别在独立的线程中执行。这些线程由操作系统来管理,在多处理器系统上可以并行处理,或者在单处理器系统上交错执行。这使得当某个线程阻塞在某个资源的同时其他线程得以继续执行。与完成类似功能的同步程序相比,这种方式更有效率,但程序员必须写代码来保护共享资源,防止其被多个线程同时访问。多线程程序更加难以推断,因为这类程序不得不通过线程同步机制如锁、可重入函数、线程局部存储或者其他机制来处理线程安全问题,如果实现不当就会导致出现微妙且令人痛不欲生的bug。
在事件驱动版本的程序中,3个任务交错执行,但仍然在一个单独的线程控制中。当处理I/O或者其他昂贵的操作时,注册一个回调到事件循环中,然后当I/O操作完成时继续执行。回调描述了该如何处理某个事件。事件循环轮询所有的事件,当事件到来时将它们分配给等待处理事件的回调函数。这种方式让程序尽可能的得以执行而不需要用到额外的线程。事件驱动型程序比多线程程序更容易推断出行为,因为程序员不需要关心线程安全问题。
当我们面对如下的环境时,事件驱动模型通常是一个好的选择:
程序中有许多任务,而且…
任务之间高度独立(因此它们不需要互相通信,或者等待彼此)而且…
在等待事件到来时,某些任务会阻塞。
当应用程序需要在任务间共享可变的数据时,这也是一个不错的选择,因为这里不需要采用同步处理。网络应用程序通常都有上述这些特点,这使得它们能够很好的契合事件驱动编程模型。
三、C/C++实现事件驱动
C/C++实现事件驱动,需要了解函数指针和回调等概念。
下面放一下之前写的相关的博客:
当然这些知识语言方面我们需要掌握的特性,要使用事件驱动编程,我们一般会使用事件驱动库。
四、常用的C/C++事件驱动库
因为一般事件驱动,都是针对的网络通信。
下面主要介绍一下libevent、libev、libuv。
Libevent、libev、libuv三个网络库,都是c语言实现的异步事件库Asynchronousevent library)。
异步事件库本质上是提供异步事件通知(Asynchronous Event Notification,AEN)的。异步事件通知机制就是根据发生的事件,调用相应的回调函数进行处理。
事件(Event):事件是异步事件通知机制的核心,比如fd事件、超时事件、信号事件、定时器事件。有时候也称事件为事件处理器(EventHandler),这个名称更形象,因为Handler本身表示了包含处理所需数据(或数据的地址)和处理的方法(回调函数),更像是面向对象思想中的称谓。
事件循环(EventLoop):等待并分发事件。事件循环用于管理事件。
对于应用程序来说,这些只是异步事件库提供的API,封装了异步事件库跟操作系统的交互,异步事件库会选择一种操作系统提供的机制来实现某一种事件,比如利用Unix/Linux平台的epoll机制实现网络IO事件,在同时存在多种机制可以利用时,异步事件库会采用最优机制。
技术对比:
1.libevent
C语言跨平台,应用最广泛,历史悠久的跨平台事件库。这是一个用纯C写的开源库,属于一个轻量级的网络中间件。其中用到的基本数据结构也是非常巧妙。展现反应堆模型的基本使用方法。不同的事件对应不容的处理方法。I/O 定时 信号。三种事件的处理单独分开,又通过事件驱动融合在一起。
优先级特性:激活的事件组织在优先级队列中,各类事件默认的优先级是相同的,可以通过设置事件的优先级使其优先被处理。
libevent在windows下支持iocp,但还不完善。
2.libev
设计更简练,性能更好,但因对Windows支持不够好。
优先级特性:激活的事件组织在优先级队列中,各类事件默认的优先级是相同的,可以通过设置事件的优先级使其优先被处理。
3.libuv
libuv是一个支持多平台的异步IO库。它主要是为了node.js而开发的。
优先级特性:没有优先级概念,按照固定的顺序访问各类事件。
因libuv为node.js定向开发,普遍应用性不好,且事件触发不可设定优先级,排除。
4.IOCP
IOCP是windows下IO事件处理的最高效的一种方式,结合OVERLAPPED IO可以实现真正的完全异步IO。不支持跨平台。
5.boost::asio
C++语言跨平台。用bind做回调也并不比虚函数好,看上去灵活了,代价却更高了。不光是运行时的内存和时间代价,编译时间也更长。基于ASIO开发应用,要求程序员熟悉函数对象,函数指针,熟悉boost库中的boost::bind,内存管理控制方面。
asio是一个高性能的网络开发库,Windows下使用IOCP,Linux下使用epoll。
-
-
Windows驱动编程基础教程
2017-09-05 11:44:11Windows驱动编程基础教程,Windows驱动编程基础教程,Windows驱动编程基础教程,Windows驱动编程基础教程,Windows驱动编程基础教程 -
事件驱动编程、消息驱动编程、数据驱动编程
2020-02-10 14:53:47事件驱动 基本概念 窗口/组件 事件 消息(队列) 事件响应(服务处理程序) 调度算法 进程/线程 非阻塞I/O 程序的执行可以看成对CPU,内存,IO资源一次占用 现代操作系统支持...事件驱动
基本概念
-
窗口/组件
-
事件
-
消息(队列)
-
事件响应(服务处理程序)
-
调度算法
-
进程/线程
-
非阻塞I/O
-
程序的执行可以看成对CPU,内存,IO资源一次占用
-
现代操作系统支持多任务,可以分时复用上述资源.
1. 为什么采用事件驱动模型?
事件驱动模型也就是我们常说的观察者,或者发布-订阅模型;理解它的几个关键点:
-
首先是一种对象间的一对多的关系;最简单的如交通信号灯,信号灯是目标(一方),行人注视着信号灯(多方);
-
当目标发送改变(发布),观察者(订阅者)就可以接收到改变;
-
观察者如何处理(如行人如何走,是快走/慢走/不走,目标不会管的),目标无需干涉;所以就松散耦合了它们之间的关系。
2. 代码执行流程
在传统的或“过程化”的应用程序中,应用程序自身控制了执行哪一部分代码和按何种顺序执行代码。从第一行代码执行程序并按应用程序中预定的路径执行,必要时调用过程。
在事件驱动的应用程序中,代码不是按照预定的路径执行-而是在响应不同的事件时执行不同的代码片段。事件可以由用户操作触发、也可以由来自操作系统或其它应用程序调度算法的消息触发、甚至由应用程序本身的消息触发。这些事件的顺序决定了代码执行的顺序,因此应用程序每次运行时所经过的代码的路径都是不同的。3. 事件驱动模型
在UI编程中,常常要对鼠标点击进行相应,首先如何获得鼠标点击呢?
方式一:创建一个线程,该线程一直循环检测是否有鼠标点击,那么这个方式有以下几个缺点:
- CPU资源浪费,可能鼠标点击的频率非常小,但是扫描线程还是会一直循环检测,这会造成很多的CPU资源浪费;如果扫描鼠标点击的接口是阻塞的呢?
- 如果是堵塞的,又会出现下面这样的问题,如果我们不但要扫描鼠标点击,还要扫描键盘是否按下,由于扫描鼠标时被堵塞了,那么可能永远不会去扫描键盘;
- 如果一个循环需要扫描的设备非常多,这又会引来响应时间的问题;所以,该方式是非常不好的。
方式二:就是事件驱动模型目前大部分的UI编程都是事件驱动模型,如很多UI平台都会提供onClick()事件,这个事件就代表鼠标按下事件。事件驱动模型大体思路如下:
-
有一个事件(消息)队列;
-
鼠标按下时,往这个队列中增加一个点击事件(消息);
-
有个循环,不断从队列取出事件,根据不同的事件,调用不同的函数,如onClick()、onKeyDown()等;
-
事件(消息)一般都各自保存各自的处理函数指针,这样,每个消息都有独立的处理函数;如图:
4. 事件驱动处理库
-
select
-
poll
-
epoll
-
libev
5.效率比较
让我们用例子来比较和对比一下单线程、多线程以及事件驱动编程模型。下图展示了随着时间的推移,这三种模式下程序所做的工作。这个程序有3个任务需要完成,每个任务都在等待I/O操作时阻塞自身。阻塞在I/O操作上所花费的时间已经用灰色框标示出来了。
在单线程同步模型中,任务按照顺序执行。如果某个任务因为I/O而阻塞,其他所有的任务都必须等待,直到它完成之后它们才能依次执行。这种明确的执行顺序和串行化处理的行为是很容易推断得出的。如果任务之间并没有互相依赖的关系,但仍然需要互相等待的话这就使得程序不必要的降低了运行速度。
在多线程版本中,这3个任务分别在独立的线程中执行。这些线程由操作系统来管理,在多处理器系统上可以并行处理,或者在单处理器系统上交错执行。这使得当某个线程阻塞在某个资源的同时其他线程得以继续执行。与完成类似功能的同步程序相比,这种方式更有效率,但程序员必须写代码来保护共享资源,防止其被多个线程同时访问。多线程程序更加难以推断,因为这类程序不得不通过线程同步机制如锁、可重入函数、线程局部存储或者其他机制来处理线程安全问题,如果实现不当就会导致出现微妙且令人痛不欲生的bug。
在事件驱动版本的程序中,3个任务交错执行,但仍然在一个单独的线程控制中。当处理I/O或者其他昂贵的操作时,注册一个回调到事件循环中,然后当I/O操作完成时继续执行。回调描述了该如何处理某个事件。事件循环轮询所有的事件,当事件到来时将它们分配给等待处理事件的回调函数。这种方式让程序尽可能的得以执行而不需要用到额外的线程。事件驱动型程序比多线程程序更容易推断出行为,因为程序员不需要关心线程安全问题。
当我们面对如下的环境时,事件驱动模型通常是一个好的选择:
程序中有许多任务,而且…
任务之间高度独立(因此它们不需要互相通信,或者等待彼此)而且…
在等待事件到来时,某些任务会阻塞。
当应用程序需要在任务间共享可变的数据时,这也是一个不错的选择,因为这里不需要采用同步处理。网络应用程序通常都有上述这些特点,这使得它们能够很好的契合事件驱动编程模型。
事件驱动机制跟消息驱动机制相比
消息驱动和事件驱动很类似,都是先有一个事件,然后产生一个相应的消息,再把消息放入消息队列,由需要的项目获取。他们的区别是消息是谁产生的
消息驱动:鼠标管自己点击不需要和系统有过多的交互,消息由系统(第三方)循环检测,来捕获并放入消息队列。消息对于点击事件来说是被动产生的,高内聚。
事件驱动:鼠标点击产生点击事件后要向系统发送消息“我点击了”的消息,消息是主动产生的。再发送到消息队列中。
事件:按下鼠标,按下键盘,按下游戏手柄,将U盘插入USB接口,都将产生事件。比如说按下鼠标左键,将产生鼠标左键被按下的事件。
消息:当鼠标被按下,产生了鼠标按下事件,windows侦测到这一事件的发生,随即发出鼠标被按下的消息到消息队列中,这消息附带了一系列相关的事件信息,比如鼠标哪个键被按了,在哪个窗口被按的,按下点的坐标是多少?如此等等。
注意:
- 要理解事件驱动和程序,就需要与非事件驱动的程序进行比较。实际上,现代的程序大多是事件驱动的,比如多线程的程序,肯定是事件驱动的。早期则存在许多非事件驱动的程序,这样的程序,在需要等待某个条件触发时,会不断地检查这个条件,直到条件满足,这是很浪费cpu时间的。而事件驱动的程序,则有机会释放cpu从而进入睡眠态(注意是有机会,当然程序也可自行决定不释放cpu),当事件触发时被操作系统唤醒,这样就能更加有效地使用cpu.
- 再说什么是事件驱动的程序。一个典型的事件驱动的程序,就是一个死循环,并以一个线程的形式存在,这个死循环包括两个部分,第一个部分是按照一定的条件接收并选择一个要处理的事件,第二个部分就是事件的处理过程。程序的执行过程就是选择事件和处理事件,而当没有任何事件触发时,程序会因查询事件队列失败而进入睡眠状态,从而释放cpu。
- 事件驱动的程序,必定会直接或者间接拥有一个事件队列,用于存储未能及时处理的事件。
- 事件驱动的程序的行为,完全受外部输入的事件控制,所以,事件驱动的系统中,存在大量这种程序,并以事件作为主要的通信方式。
- 事件驱动的程序,还有一个最大的好处,就是可以按照一定的顺序处理队列中的事件,而这个顺序则是由事件的触发顺序决定的,这一特性往往被用于保证某些过程的原子化。
- 目前windows,linux,nucleus,vxworks都是事件驱动的,只有一些单片机可能是非事件驱动的。
事件模式耦合高,同模块内好用;消息模式耦合低,跨模块好用。事件模式集成其它语言比较繁琐,消息模式集成其他语言比较轻松。事件是侵入式设计,霸占你的主循环;消息是非侵入式设计,将主循环该怎样设计的自由留给用户。如果你在设计一个东西举棋不定,那么你可以参考win32的GetMessage,本身就是一个藕合度极低的接口,又足够自由,接口任何语言都很方便,具体应用场景再在其基础上封装成事件并不是难事,接口耦合较低,即便哪天事件框架调整,修改外层即可,不会伤经动骨。而如果直接实现成事件,那就完全反过来了。什么是数据驱动编程
正题
作者在介绍Unix设计原则时,其中有一条为“表示原则:把知识叠入数据以求逻辑质朴而健壮”。结合之前自己的一些经验,我对这个原则很有共鸣,所以先学习了数据驱动编程相关的内容,这里和大家分享出来和大家一起讨论。
核心
数据驱动编程的核心出发点是相对于程序逻辑,人类更擅长于处理数据。数据比程序逻辑更容易驾驭,所以我们应该尽可能的将设计的复杂度从程序代码转移至数据。
真的是这样吗?让我们来看一个示例。假设有一个程序,需要处理其他程序发送的消息,消息类型是字符串,每个消息都需要一个函数进行处理。第一印象,我们可能会这样处理:
void msg_proc(const char *msg_type, const char *msg_buf) { if (0 == strcmp(msg_type, "inivite")) { inivite_fun(msg_buf); } else if (0 == strcmp(msg_type, "tring_100")) { tring_fun(msg_buf); } else if (0 == strcmp(msg_type, "ring_180")) { ring_180_fun(msg_buf); } else if (0 == strcmp(msg_type, "ring_181")) { ring_181_fun(msg_buf); } else if (0 == strcmp(msg_type, "ring_182")) { ring_182_fun(msg_buf); } else if (0 == strcmp(msg_type, "ring_183")) { ring_183_fun(msg_buf); } else if (0 == strcmp(msg_type, "ok_200")) { ok_200_fun(msg_buf); } 。。。。。。 else if (0 == strcmp(msg_type, "fail_486")) { fail_486_fun(msg_buf); } else { log("未识别的消息类型%s\n", msg_type); } }
上面的消息类型取自sip协议(不完全相同,sip协议借鉴了http协议),消息类型可能还会增加。看着常常的流程可能有点累,检测一下中间某个消息有没有处理也比较费劲,而且,没增加一个消息,就要增加一个流程分支。按照数据驱动编程的思路,可能会这样设计:
typedef void (*SIP_MSG_FUN)(const char *); typedef struct __msg_fun_st { const char *msg_type;//消息类型 SIP_MSG_FUN fun_ptr;//函数指针 }msg_fun_st; msg_fun_st msg_flow[] = { {"inivite", inivite_fun}, {"tring_100", tring_fun}, {"ring_180", ring_180_fun}, {"ring_181", ring_181_fun}, {"ring_182", ring_182_fun}, {"ring_183", ring_183_fun}, {"ok_200", ok_200_fun}, 。。。。。。 {"fail_486", fail_486_fun} }; void msg_proc(const char *msg_type, const char *msg_buf) { int type_num = sizeof(msg_flow) / sizeof(msg_fun_st); int i = 0; for (i = 0; i < type_num; i++) { if (0 == strcmp(msg_flow[i].msg_type, msg_type)) { msg_flow[i].fun_ptr(msg_buf); return ; } } log("未识别的消息类型%s\n", msg_type); }
数据驱动优势
1、可读性更强,消息处理流程一目了然。
2、更容易修改,要增加新的消息,只要修改数据即可,不需要修改流程。
3、重用,第一种方案的很多的else if其实只是消息类型和处理函数不同,但是逻辑是一样的。下面的这种方案就是将这种相同的逻辑提取出来,而把容易发生变化的部分提到外面。
隐含在背后的思想:
很多设计思路背后的原理其实都是相通的,隐含在数据驱动编程背后的实现思想包括:
1、控制复杂度。通过把程序逻辑的复杂度转移到人类更容易处理的数据中来,从而达到控制复杂度的目标。
2、隔离变化。像上面的例子,每个消息处理的逻辑是不变的,但是消息可能是变化的,那就把容易变化的消息和不容易变化的逻辑分离。
3、机制和策略的分离。和第二点很像,本书中很多地方提到了机制和策略。上例中,我的理解,机制就是消息的处理逻辑,策略就是不同的消息处理(后面想专门写一篇文章介绍下机制和策略)。
数据驱动可以用来做什么:
如上例所示,它可以应用在函数级的设计中。
同时,它也可以应用在程序级的设计中,典型的比如用表驱动法实现一个状态机(后面写篇文章专门介绍)。
也可以用在系统级的设计中,比如DSL(这方面我经验有些欠缺,目前不是非常确定)。
它不是什么:
1、 它不是一个全新的编程模型:它只是一种设计思路,而且历史悠久,在unix/linux社区应用很多;
2、它不同于面向对象设计中的数据:“数据驱动编程中,数据不但表示了某个对象的状态,实际上还定义了程序的流程;OO看重的是封装,而数据驱动编程看重的是编写尽可能少的代码。”
书中的值得思考的话:
数据压倒一切。如果选择了正确的数据结构并把一切组织的井井有条,正确的算法就不言自明。编程的核心是数据结构,而不是算法。——Rob Pike
程序员束手无策。。。。。只有跳脱代码,直起腰,仔细思考数据才是最好的行动。表达式编程的精髓。——Fred Brooks
数据比程序逻辑更易驾驭。尽可能把设计的复杂度从代码转移至数据是个好实践。——《unix编程艺术》作者。
转载自:学时网 » 事件驱动编程、消息驱动编程、数据驱动编程
-
-
Windows驱动编程和Windows_API_参考大全资料包
2018-06-02 22:10:48此资料包里面包括了Windows驱动编程和Windows_API_参考资料,对于想在Windows系统底层进行开发和研究的同学,此资料包是个不错的选择 -
windows硬件驱动编程教程.zip
2021-01-25 15:58:37windows硬件驱动编程教程 -
windows驱动编程大全
2012-10-26 17:16:49Windows 2000XP WDM设备驱动程序开发 第二版.pdf window2000内部揭密.pdf Microsoft+Windows驱动程序模型设计.pdf -
ecard.rar_驱动编程_Windows_Unix_
2021-08-11 21:32:14ecard驱动包 深圳德卡科技有限公司 刷卡专用 -
si32.rar_驱动编程_Windows_Unix_
2021-08-12 06:46:37PCI modem Windows_SM56_6.12.07_DFV Cis32 -
fmqn8025.rar_驱动编程_Windows_Unix_
2021-08-12 04:07:46FM芯片QN8025驱动程序 -
《楚狂人Windows驱动编程基础教程》
2018-03-21 16:10:44楚狂人写的一本关于驱动开发的很好的学习教程,里面的知识点很多。对初学者很好帮助。 -
寒江独钓-Windows内核安全编程完整版(内附源码)
2019-01-25 18:10:37完整的零基础学习windows下驱动编程(内附源码)。内核编程环境配置;串口过滤、键盘过滤;磁盘虚拟;磁盘过滤;文件系统过滤与监控;文件系统透明加密;文件系统微过滤;网络传输层过滤;NDIS协议驱动;NDIS小端口... -
jh_pci.rar_驱动编程_Windows_Unix_
2021-08-12 02:01:37windows上的PCI驱动,包括驱动程序入口,IO控制处理等。 -
POS-58.rar_驱动编程_Windows_Unix_
2021-08-11 23:45:13driver for POS 58 printer -
Windows驱动编程入门.pdf
2021-10-09 01:10:58Windows驱动编程入门.pdf -
Windows驱动开发系列之三:WDF驱动开发入门
2021-06-30 23:16:241)WDF编程框架:面向对象和事件机制 2)WDF重要对象:驱动对象、设备对象、IO队列、IO请求、等 3)事件回调函数:从派遣函数到事件回调函数的原理流程解析 4)WDF过滤驱动:掌握WDF对IRP的处理,以及过滤驱动的应用... -
DriverGenius_v2009b2_bd.rar_驱动编程_Windows_Unix_
2021-08-12 01:58:26驱动精灵2009 驱动更新 备份 还原 软件 -
WP-T800-ver.2.94.rar_驱动编程_Windows_Unix_
2021-08-11 20:25:03收银系统、POS系统等的莹浦通WP-t800 2.94版本的驱动程序 -
Windows驱动编程教程
2014-03-13 10:11:07Windows驱动编程教程简介:本书www.tomzw.com编写非常适合熟悉Windows 应用编程的读者转向驱动开发。所有的内容都从最基础的编程方法入手。介绍相关的内核API,然后举出示范的例子。这本书只有不到70 页,是一本非常... -
寒江独钓-Windows内核安全编程(完整版) pdf
2018-09-09 16:53:19寒江独钓-Windows内核安全编程(完整版) -
windows驱动视频教程第六课!
2018-09-16 08:56:25windows驱动视频教程第六课! -
windows内核驱动编程基础
2012-04-30 13:37:12windows内核驱动编程基础 详细介绍windows内核驱动的编程技术 -
事件驱动编程机制在嵌入式GUI系统中的实现 (2009年)
2021-06-19 00:36:34针对嵌入式 GUI中使用事件驱动编程机制实现窗口和控件的开发进行了讨论,分析了自主开发的TBGUI的体系结构和特点,提供了一种完全实用的嵌入式系统中的类 Windows图形用户界面。 TBGUI适合以单片机为主的 8位、16位... -
Windows2000DeviceDriverDevelopment.rar_驱动编程_C/C++_
2021-08-12 04:36:37Windows2000设备驱动程序开发大全 -
EZP2010 编程器win10驱动.rar
2020-08-16 22:09:03通过更改win10系统环境,让EZP2010编程器在win10环境下运行,压缩包中含有适合EZP2010win10驱动文件,ezp2011编程器工具,ezp2010 v3固件升级包,文本详细介绍如何操作 -
Windows虚拟鼠标键盘驱动
2018-01-18 13:59:16Windows虚拟鼠标键盘驱动 完整源代码包含visual studio项目文件 -
Windows内核安全与驱动开发随书代码.rar
2019-05-28 11:44:21本书的前身是《天书夜读——从汇编语言到Windows内核编程》和《寒江独钓——Windows内核安全编程》。与Windows客户端安全软件开发相关的驱动程序开发是本书的主题。书中的程序使用环境从32位到64位,从Windows XP到... -
Windows编程—Windows驱动开发环境搭建
2020-07-02 09:38:48作为一个编写Windows程序的开发人员,对Windows驱动开发 并非必需要掌握,但是掌握 Windows驱动开发对Windows程序开发人员却有极大的好处。一个直观的感受 程序操作权限更大了,因为处在内核层了嘛。应该可以写更...前言
作为一个编写Windows程序的开发人员,对Windows驱动开发 并非必需要掌握,但是掌握 Windows驱动开发对Windows程序开发人员却有极大的好处。一个直观的感受 程序操作权限更大了,因为处在内核层了嘛。应该可以写更厉害的外挂,普通Windows程序写个辅助完全是没问题的,但是涉及到数据修改突破游戏程序的一些限制 必须用更高权限的内核驱动了。
开始学习Windows驱动开发,第一步当然是环境搭建了。因为笔者也在驱动环境搭建上也吃过亏,所以这里进行记录和分享,当然这里也是集众家之长了。
其实笔者在一开始学Windows程序开发的时候 搭过一次驱动开发环境,当时直接用vs2015还是vs2017 忘了,使用WDK10,搭了好几周 都没搭成功,最后 无奈放弃。总结下失败原因,WDK10的版本众多 而且还要和当前 操作系统一一对应,而且win10 又经常更新,当时调试机也是用的win10版本,笔者电脑配置也不行 开win10虚拟机也吃力。
这里笔者建议初学者 不要一开始 就WDK10 和 VS集成开发 调试。先使用windbg 把双机调试搞起来了 再说。其实vs集成开发调试 也是调用的windbg。这里顺带说一下 WDK版本和操作系统版本关系。WDK 7600_1 在主机最低Win7安装,编译出来的驱动 最低支持到Win XP,VS未集成。WDK8.1 在主机最低Win8上安装,编译出来的驱动最低支持Win Visa,VS2013开始集成。WDK 10具体版本 就具体细化了 编译出来的驱动最低支持到Win7。基本上做Win开发 都是以 Win XP作为 支持的最后底线,所以一般 我们用WDK7即可了。
笔者这里环境是 主机Win10 + WDK7600_1 + 调试机Win XP Sp3 。
步骤
步骤一
在win10上安装 WDK7600_1,将GRMWDK_EN_7600_1.ISO 解压安装即可。百度云下载链接
链接:https://pan.baidu.com/s/1ldYMIIn6837iq2IYUpNSqg
提取码:3lex
或者 网上搜索,都可以找到。步骤二
使用VMware安装Win XP Sp3虚拟机,安装完毕后,在C:\boot.ini中添加调试模式启动选项。添加后如下:
[boot loader] timeout=30 default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS [operating systems] multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect /debug /debugport=com1 /baudrate=115200
此时如果重启,显示页面应该如下,说明boot.ini配置好了。
随后添加串行端口。用于主机与调试机通信使用的。
步骤三
配置WinDbg
File -> Kernel Debugging -> COM 进行如下配置,端口和波特率要和 虚拟机配置一样。
也可以 将windbg.exe 发送到桌面快捷方式,在快捷方式 -> 属性-> 快捷方式 -> 目标 空格后添加如下参数,这样以后 双击 就开始会连接调试机。
// 目标程序后面 添加如下参数 -b -k com:port=\\.\pipe\com_1,baud=115200,pipe // 下面是笔者的目标 D:\WinDDK\7600.16385.1\Debuggers\windbg.exe -b -k com:port=\\.\pipe\com_1,baud=115200,pipe
连接测试
在步骤二、三 完全配置好了就可以 测试 双机调试 是否连通通了,重启 Win Xp Sp3,可以在启动项 那里来回切,这样就停在那里了。此时 调试机 的串口已经启动了,此时可以进行步骤三 进行连接了。
此时可以点击 WinXp 调试启动了。
此时WinDbg如下:
此时,虚拟机也会被暂停,在kd> g 继续,测试虚拟机正常启动。
在虚拟机中可以加载驱动进行测试,看windbg是否有输出,调试机 连接 windbg 调试,请看步骤五。
步骤四
配置系统内核符号表。笔者用的Win XP Sp3 x86版本,下的符号表 WindowsXP-KB936929-SP3-x86-symbols-full-ENU.exe 这个,本来微软可以在线获取符号表,笔者自己测试 貌似没起效果 没有进行在线获取。百度云链接:
链接:https://pan.baidu.com/s/1ABA8qcealpBKr_Op2QF_Pw
提取码:wmi3笔者这里选择的安装目录时在 C:\symbols。这里一定要注意,我们配置符号表路径 不能直接是根目录,一定得 具体到下面的子目录 才是 pdb路径。
在 系统环境路径配置如下:
_NT_SYMBOL_PATH F:\Book\Windows\Windows内核安全与驱动开发随书源代码\first\objchk_wxp_x86\i386;C:\Symbols\acm;C:\Symbols\ax;C:\Symbols\cnv;C:\Symbols\com;C:\Symbols\cpl;C:\Symbols\dic;C:\Symbols\dll;C:\Symbols\drv;C:\Symbols\ds;C:\Symbols\exe;C:\Symbols\iec;C:\Symbols\ime;C:\Symbols\ocx;C:\Symbols\scr;C:\Symbols\sys;C:\Symbols\tpl;C:\Symbols\tsp;C:\Symbols\wpc;SRV*C:\Symbols_cache*http://msdl.microsoft.com/download/symbols;
笔者这里是 把测试的sys驱动的 pdb路径配置上,然后再才是本地Win XP Sp3系统符号表,最后再才是 在线获取符号表配置(笔者这里测试貌似不起效果)。
配置完了后,可以重写进行连接测试,走到 kd> 命令行处,或者如果在运行时直接 Debug -> Break 也会进行中断到 kd> 命令行处,我们进行一些简单测试。
// 1、查看设置的符号表路径,如果查找出来不是签名配置的路径,可以在WinDbg->File->Symbol File Path 将路径路径拷贝进入勾上Reload框 然后点击OK。 就会重新加载符号文件路径了。 kd> .sympath // 2、查看相应的模块信息,如果能查找系统模块pdb说明 我们配置系统符号表没问题 kd> !lmi ntkrpamp
步骤五
我们准备一个 测试用的sys,看能否进入断点调试。我们只需要找一个可以加载装载驱动的软件就可以了。这里笔者用 Driver Monitor软件来加载驱动。
这里准备一个sys文件,这里笔者直接用<< Windows内核安全与驱动开发 >> 随书源代码中的 first例子。使用 x86 Free Build Environment(安装好wdk后,在启动菜单可以找到) 进行编译,cd 切换到first.sys目录,然后build。会生成如下的 first.pdb和first.sys。
first.c
/// /// @file first.c /// @author crazy_chu /// @date2008-11-1 /// #include <ntddk.h> // 提供一个Unload函数只是为了 VOID DriverUnload(PDRIVER_OBJECT driver) { // 但是实际上我们什么都不做,只打印一句话: DbgPrint("first: Our driver is unloading…\r\n"); } // DriverEntry,入口函数。相当于main。 NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path) { #if DBG _asm int 3 #endif // 这是我们的内核模块的入口,可以在这里写入我们想写的东西。 // 我在这里打印一句话。因为”Hello,world” 常常被高手耻笑,所以 // 我们打印一点别的。 DbgPrint("first: Hello, my salary!\r\n"); // 设置一个卸载函数便于这个函数能退出。 driver->DriverUnload = DriverUnload; return STATUS_SUCCESS; }
这个路径 要添加到 环境变量_NT_SYMBOL_PATH 或者 WDK中的 sympath中去。
我们把first.sys 拷贝到 虚拟机中,然后使用 monitor,File ->Open Driver first.sys ,然后再File->Start Driver 这时会去装载驱动,然后再File->Stop Driver 这时会去 卸载驱动。
总结
作为初学者,建议先把 windbg双机调试模式 搞起来这才是王道,vs集成驱动开发可以后面再搞。笔者认为 win10 + wdk7 + win xp sp3 双机调试也是最省配置的。
-
Windows.7.Device.Driver.rar_驱动编程_C/C++_
2021-08-11 20:20:26[Windows.7.设备驱动程序开发].(Windows.7.Device.Driver).Reeves