异步过程调用(APC -- Asynchronous Procedure Call )是一种与常用的和简单的同步对象不同的一种同步机制。

我们在我们线程里使用基本的同步对象如MUTEX去通知其它线程,它应该停下来等我们完成之后你再继续。APCs使用了一种不同的策略,

因此可能要求应用程序不同的设计。一个APC是一种回调函数类型。与普通的函数指针在调用上有些类似。我们能够在需要通知其它任务一

些事情时可以调用这样的函数。这个任务将在回调函数内部处理这个事件,而不是等待该事件并在通知后继续工作,实际的工作写在了回调

函数里。普通回调函数将在调用者上下文中执行该函数。例如,线程A调用回调函数,则回调函数运行在线程A的上下文中,同时线程B也正

在做一些事情。想一下,一个线程正在重画窗体,而另外一个线程有一些新的信息要显示在窗口上。

这里的APC机制解决了同步问题,而不需要MUTEX或者Event来包含共享资源。当一个线程使用APC时它告诉系统让其他线程调用该回调函

数时运行在回调函数自己上下文中。换句话说,任务A告诉任务B去执行一个函数。任务B将不中断它自己的工作区执行这个动作。相反它将

完成所有的事情,然后去执行该回调函数。这种同步假设了回调函数将在任务完成之后才被调用,所以它已经完成了资源的使用。看一下画

图的这个例子,它完成了画整个窗体后才开始更新新数据。

APC的机制将等待目标任务完成它的所有工作。因为今天的应用程序大部分时间是在等待下一个系统事件,它假设当任务完成了所有工作,

然后进入一个等待状态知道下一系统事件到来。操作系统(同步库)将偷走这个任务的事件等到该任务进入等待状态时,并跳到了回调函数

的地址上。当函数返回时,该任务将回来在原始的代码或函数上继续等待。

使用同步机制要求在操作期间不等待,所以我们在处理资源时不需要使用MUTEX或事件。

APC是一个在特定线程中执行的函数。当一个APC压入APC队列时,系统将引发一个软中断。接下来该线程将被调度,并运行该APC函数。

APC有2中类型:内核模式的APC和用户模式的APC;内核模式APC由系统产生,而用户模式的由应用程序产生。

每一个线程都有自己的APC队列。可以使用QueueUserAPC函数把一个APC函数压入APC队列中。APC排队就是请求线程调用APC函数。

当用户模式的APC压入线程APC队列后,该线程并不直接调用APC函数,除非该线程是处于可通知状态。当一个线程调用SleepEx,

SignalObjectAndWait、MsgWaitForMultipleObjectsEx,WaitForMultipleObjectsEx或者WaitForSingleObjectEx函数时,它才进入可

通知状态。如果在APC压入队列之前,线程进入可通知状态,则该APC函数将不被执行,因为此时该线程并不是处于可通知状态。然而,该

APC函数仍然在队列中,所以在下次调用可通知状态函数时,它将被调用。

ReadFileEx,SetWaitableTime,SetWaitableTimerEx和WriteFileEx函数是使用一个作为完成通知回调机制的APC来实现的。

如果你正在使用一个线程池,那么注意该APC并不能和其它信号机制一起工作。因为系统控制了线程池的生命周期,可能在通知之前该线程

被终止了。应该使用可等待对象比如CreateThreadpoolTimer创建的定时器,而不是基于APC的通知机制--如SetWaitableTimer或

SetWaitableTimerEx的参数pfnCompletionRoutine。对于I/O,使用一个用CreateThreadpoolIo创建的I/O完成对象或者一个基于事件的

OVERLAPPED结构体传递到SetThreadpoolWait函数中。

当一个发起I/O请求时,一个结构体被分配来表示该请求。该结构体称为I/O请求包(IRP -- I/O request packet)。同步I/O,线程将构造

这个IRP,并发送到设备栈,等待内核完成IRP。异步I/O,线程构造IRP并发送个设备栈。设备栈可能立即完成IRP,也可能返回一个

pending状态,告诉线程正在处理中。这时,该IRP仍然关联着线程,所以该线程终止时或者调用CancelIo时该IRP将被取消。同时,线程在

处理设备栈的IRP时能够继续执行其它任务。

有以下几种方法知道IRP已经完成:
当IRP完成时将用操作结果更新overlapped结构体,所以线程能够轮询操作是否完成。
当IRP完成时将触发overlapped结构体中的event时,所以当操作完成时,线程能同步并处理。
把IRP压入线程未决的APC时,当线程处于可通知状态时将执行APC函数并返回等待操作带有指示它执行一个或多个APC函数的状态。
把IRP压入一个I/O完成端口时,它将被等待该完成端口的下一个线程执行。

等待IO完成端口的线程并不等待可通知状态。因此,如果这些线程发起了被作为APC设置为完成的IRP到线程时,这些IPC完成不能及时地发

生;它们将在线程从IO完成端口获得请求并碰巧进入了可通知状态时才发生。

http://asyncop.com/link.aspx?apc
http://msdn.microsoft.com/en-us/library/windows/desktop/ms681951%28v=vs.85%29.aspx

APC -- Asynchronous Procedure Call 异步过程调用的更多相关文章

  1. WINDOWS硬件通知应用程序的常方法(五种方式:异步过程调用APC,事件方式VxD,消息方式,异步I/O方式,事件方式WDM)

    摘要:在目前流行的Windows操作系统中,设备驱动程序是操纵硬件的最底层软件接口.为了共享在设备驱动程序设计过程中的经验,给出设备驱动程序通知应用程序的5种方法,详细说明每种方法的原理和实现过程,并 ...

  2. APC (Asynchronous Procedure Call)

    系统创建新线程时,会同时创建与这个线程相关联的队列,即异步过程调用(APC)的队列. 一些异步操作可以通过加入APC来实现,比如我现在学习的IO请求/完成. BOOL ReadFileEx( HAND ...

  3. 通过异步程序调用(APC)实现的定时功能

    定时器是一个在特定时间或者规则间隔被激发的内核对象.结合定时器的异步程序调用可以允许回调函数在任何定时器被激发的时候执行.本文的例子代码显示了如何实现. 使用本定时器时,你需要把常量_WIN32_WI ...

  4. win32多线程-异步过程调用(asynchronous Procedure Calls, APCs)

    使用overlapped I/O并搭配event对象-----win32多线程-异步(asynchronous) I/O事例,会产生两个基础性问题. 第一个问题是,使用WaitForMultipleO ...

  5. RPC-远程过程调用协议

    远程过程调用协议 同义词 RPC一般指远程过程调用协议 RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要 ...

  6. ARM过程调用标准---APCS简单介绍

    介绍 APCS,ARM 过程调用标准(ARM Procedure Call Standard),提供了紧凑的编写例程的一种机制,定义的例程能够与其它例程交织在一起.最显著的一点是对这些例程来自哪里没有 ...

  7. Java同步和异步过程中消息语言国际化处理策略

    在Java后端做消息内容的语言国际化处理时可以通过Spring中MessageSource接口的来实现,但是MessageSource接口需要用到Locale对象, 而Locale类又是根据前端传过来 ...

  8. 进程内部异步事件调用组件Async-Event

    项目坐标:https://github.com/cncduLee/async-event async-event 进程内部异步事件调用组件 解决什么问题: 加速服务处理效率.提供进程级别的事件发布和异 ...

  9. 从汇编角度分析C语言的过程调用

    ➠更多技术干货请戳:听云博客 基本术语定义 1.系统栈(system stack)是一个内存区,位于进程地址空间的末端. 2.在将数据压栈时,栈是自顶向下增长的,该内存区用于函数的局部变量提供内存.它 ...

随机推荐

  1. 配置iSCSI多路径

    1.添加MPIO功能,完成后打开MPIO进行配置,添加对iSCSI多路径的支持,如下图表示已经添加完成后灰色不可选,再打开 MPIO设备 标签页可以看到已安装完成的MPIO所支持的设备:

  2. HDU 5536 Chip Factory 字典树

    Chip Factory Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid= ...

  3. BZOJ 1051: [HAOI2006]受欢迎的牛 缩点

    1051: [HAOI2006]受欢迎的牛 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/ ...

  4. [置顶] VC++界面编程之--自定义CEdit(编辑框)皮肤

    自定义编辑框是登陆界面经常用到的效果,所以我也模仿站酷网的素材做了个. 要想继承CCustomDraw来完全自绘CEdit控件,是不太可行的方案,因为一旦你完全重绘,那么你需要额外做以下几件事: 1. ...

  5. php 下载远程图片 的几种方法(转)

    1.获取远程文件大小及信息的函数 function getFileSize($url){          $url = parse_url($url);          if($fp = @fso ...

  6. placement new 操作符

    placement new操作符能够在分配内存时指定内存位置.下面的程序使用了placement new操作符和常规new操作符给对象分配内存. // placenew.cpp -- new, pla ...

  7. Javassist初体验

           最初接触javassist是在研究dubbo源码的时候,那会对其的理解还停留在动态生成字节码的位置,可以做动态代理之类的动态化处理.最近由于项目需要扫描springMVC中control ...

  8. 面向对象设计原则OO

    面向对象设计原则是OOPS(Object-Oriented Programming System,面向对象的程序设计系统)编程的核心,但大多数Java程序员追逐像Singleton.Decorator ...

  9. js学习笔记第二篇

    Js笔记整理 1.StringAPI a)        大小写转换:str.toUpperCase();str.toLowerCase(); b)        获取指定位置字符: Str[i]-- ...

  10. 小白日记16:kali渗透测试之弱点扫描-openvas、nessus

    漏洞扫描工具 1.openvas OpenVAS是开放式漏洞评估系统,也可以说它是一个包含着相关工具的网络扫描器.在kali上默认集成openvas.在kali上,配置相对简单[几乎每天都在更新] 实 ...