`
yexin218
  • 浏览: 973041 次
  • 性别: Icon_minigender_1
  • 来自: 珠海
社区版块
存档分类
最新评论

纵横捭阖C++之从异步谈起

阅读更多

一般来说,简单的异步(Asynchronous)调用是这样一种调用方式:发起者请求一个异步调用,通知执行 者,然后处理其他工作,在某一个同步点等待执行者的完成;执行者执行调用的实际操作,完成后通知发起者。可以看出,在异步调用中有两种角色:发起者和执行 者,它们都是能主动运行的对象,我们称为主动对象,同时还有一个同步点,主动对象在同步点协调同步。在本文中,我们讨论主要是通用计算机、多进程多线程的 分时操作系统上的异步调用。在操作系统的角度上来看,主动对象包括了进程、线程和硬件上的IC等,至于中断,可以看作总是在某个进程或者线程的上下文借用 一下CPU。而同步操作可以通过操作系统得各种同步机制:互斥锁,信号灯等等来完成。

我们可以先看看异步调用在Windows(本文中一般不加指出的话,都是特指NT/2000)读写文件中的应用。Windows中的ReadFile和 WriteFile都提供了异步的接口。以ReadFile为例,

BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);

 如果最后一个 参数lpOverlapped不为NULL,并且文件以FILE_FLAG_OVERLAPPED标志打开,那么这个调用就是异步的:ReadFile会 立刻返回,如果操作没有立刻完成(返回FALSE并且GetLastError()返回ERROR_IO_PENDING),那么调用者可以在某个时刻通 过WaitForSingleObject等函数来等待中的hEvent来等待操作完成(可能已经完成)进行同步,当操作完成以后,可以调用 GetOverlappedResult者获得操作的结果,比如是否成功,读取了多少字节等等。这里的发起者就是应用程序,而执行者就是操作系统本身,至 于执行者是怎么执行的,我们会在后面的篇幅讨论。而两者的同步就是通过一个Windows Event来完成。

把这个异步调用的过程 再抽象和扩展一些,我们可以把异步调用需要解决的问题归结为两个:一个是执行的动力,另一个是主动对象的调度。简单来说,前者是各个主动对象(线程、进程 或者一些代码)是如何获得CPU,后者是各个主动对象如何协同工作,保证操作的流程是协调正确的。一般来说,进程和线程都可以由操作系统直接调度而获得 CPU,而更细粒度的,比如一些代码的调度,往往就需要一个更复杂的模型(比如在操作系统内部的实现,这时候线程的粒度太粗了)。而主动对象的调度,当参 与者较少的时候,可以通过基本的同步机制来完成,在更复杂的情况下,可能通过一个schedule机制来做会更实际一些。

动力和调度

如前所述,异步调用主要需要解决两个问题:执行的动力和执行的调度。最普遍的情况就是,一个主导流程的调用者进程(线程),一个或多个工作者进程(线 程),通过操作系统提供的同步机制来完成异步调用。这个同步机制在扩展化的情形下,是一个或多个栅栏Barrier,对应于每个同步的执行点。所有需要在 这个执行点同步的主动对象会等待相应的Barrier,直到所有对象都完成。在一些简化的情形,比如说工作者并不关心调用者的同步,那么这个 Barrier可以简化成信号灯,在只有一个工作者的情况下,可以简化成一个Windows事件Event或者条件变量 Condition Variable。

现在来考虑复杂的情形。假设我们用一些线程来协作完成一项工作,各个线程的执行之间有先后顺序上的限制,而操作系 统就是这项工作的调度者,负责在适当的时候调度适当的线程来获得CPU。显然,并发执行中的一个线程对于另外一个线程来说,本质上就是异步的,假如它们之 间有调用关系,那也就是一个异步调用。而操作系统可以通过基本的同步机制使得合适的线程才被调度,其他未完成的线程则处于等待状态。举例说,我们有4个线 程A,B,C,D来完成一项工作,其中的顺序限制是A>B;C>D,“>”表示左边的线程完成必须先于右边的线程执行,而“;”表示两 个线程可以同时进行。同时假设B的一个操作需要调用C来完成,显而易见,这时候这个操作就是一个异步调用。我们可以在每个“>”的位置设定一个同步 点,然后通过一个信号灯来完成同步。线程B,C等待第一个信号灯,而D会等待第二个信号灯。这个例子的动力和调度都是通过操作系统的基本机制(线程调度和 同步机制)来完成。

把这个过程抽象一下,可以描述为:若干个主动对象(包括代码)协调来完成一项工作,通过一个调度器来调度,实际 上,这个调度器可能只是一些调度规则。显然,进程或者线程只要被调度就能获得CPU,所以我们主要考虑代码(比如一个函数)怎么样才能获得执行。用工作者 线程来调用这个函数显然是直观和通用的一个方案。事实上,在用户空间(user space)或者用户态(user mode),这个方法是很常用的。而在内核态(kernel mode),则可以通过中断来获得CPU,这个通过注册IDT入口和触发软中断就可以完成。硬件设备上的IC是另一个动力之源。而主动对象的调度,最基本 的也是前面说的各种同步机制。另一个常用的机制就是回调函数,需要注意的是,回调函数一般会发生在跟调用者不一样的上下文,比如说同一个进程的不同线程, 这个差别会带来一些限制。如果需要回调发生在调用者的进程(线程)上下文,则需要一些类似Unix下的signal或者Windows下的APC机制,这 一点我们在后面会有所阐述。那么在回调函数里面一般作些什么事情呢?最常用的,跟同步机制结合在一起,当然就是释放一个互斥锁,信号灯或者Windows Event(Unix的条件变量)等等,从而使得等待同步的其他对象可以得到调度而重新执行,实际上,也可以看作是通知调度器(操作系统)某些主动对象 (等待同步的)可以重新被调度了,从而调度器重新调度。但是对于另外一些调度器,在这个过程中可能不需要同步对象的参与。在一些极端一些的例子里,调度甚 至不要求严格有序的。

在实际应用中,根据环境的限制,异步调用的动力和调度的实现方式可以有很大差别。我们会在后面的例子里加以说明。 操作系统中的异步:Windows的异步I/O。

Windows NT/2000是一个抢占式的分时操作系统。Windows的调度单位是线程,它的 I/O架构是完全异步的,也就是说同步的I/O实际上都基于异步I/O来完成。一个用户态的线程请求一个I/O的时候会导致一个运行状态从user mode到kernel mode的转变(操作系统把内核映射到每个进程的2G-4G的地址上,对于每个进程都是一样的)。这个过程是通过中断调用内核输出的一些System Service来完成,比如说ReadFile实际上会执行NtReadFile(ZwReadFile),需要注意的是,运行上下文仍然是当前线程。 NtReadFile的实现则基于Windows内核的异步I/O框架,在I/O Manager的协助下完成。需要指出的是,I/O Manager只是由若干API构成的一个抽象概念,并没有一个真正的I/O Manager线程在运行。

Windows的I/O驱 动程序是层次堆积的。每个驱动程序会提供一致的接口以供初始化、清理和功能调用。驱动程序的调用基于I/O请求包(I/O Request Packet, IRP),而不是像普通的函数调用那样使用栈来传递参数。操作系统和PnP管理器根据注册表在适当的时机初始化和清理相应的驱动程序。在一般的功能调用的 时候,IRP里面会指定功能调用号码以及相应的上下文或者参数(I/O stack location)。一个驱动程序可能调用别的驱动程序,这个过程可能是同步的(线程上下文不改变),也可能是异步的。NtReadFile的实现,大致 是向最上层的驱动程序发出一个或多个IRP,然后等待相应事件的完成(同步的情况),或者直接返回(带Overlapped的情况),这些都在发起请求的 线程执行。

当驱动程序处理IRP的时候,它可能立刻完成,也可能在中断里才能完成,比如说,往硬件设备发出一个请求(通常可以是写 I/O port),当设备完成操作的时候会触发一个中断,然后在中断处理函数里得到操作结果。Windows有两类中断,硬件设备的中断和软中断,分成若干个不 同的优先级(IRQL)。软中断主要有两种:DPC(Delayed Procedure Call)和APC(Asynchronous Procedure Call),都处于较低的优先级。驱动程序可以为硬件中断注册ISR(Interrupt Service Routine),一般就是修改IDT某个条目的入口。同样,操作系统也会为DPC和APC注册适当的中断处理例程(也是在IDT中)。

值得指出的是,DPC是跟处理器相关的,每个处理器会有一个DPC队列,而APC是跟线程相关的,每个线程会有它的APC队列(实际上包括一个 Kernel APC队列和User APC队列,它们的调度策略有所区别),可以想象,APC并不算严格意义上的中断,因为中断可能发生在任何一个线程的上下文中,它被称为中断,主要是因为 IRQL的提升(从PASSIVE到APC),APC的调度一般在线程切换等等情形下进行。当中断发生的时候,操作系统会调用中断处理例程,对于硬件设备 的ISR,一般处理是关设备中断,发出一个DPC请求,然后返回。不在设备的中断处理中使用太多的CPU时间,主要考虑是否则可能丢失别的中断。由于硬件 设备中断的IRQL比DPC中断的高,所以在ISR里面DPC会阻塞,直到ISR返回IRQL回到较低的水平,才会触发DPC中断,在DPC中断里执行从 硬件设备读取数据以及重新请求、开中断等操作。ISR或者DPC可能在任何被中断的线程上下文(arbitrary thread context)执行,事实上线程的上下文是不可见的,可以认为是系统借用一下时间片而已。

总的来说,Windows的异步I/O架 构中,主要有两种动力,一是发起请求的线程,一部分内核代码会在这个线程上下文执行,二是ISR和DPC,这部分内核代码会在中断里完成,可能使用任何一 个线程的上下文。而调度常见使用回调和事件(KEVENT),比如说在往下一层的驱动程序发出请求的时候,可以指定一个完成例程Completion Routine,当下层的驱动完成这个请求的时候会调用这个例程,而往往在这个例程里,就是简单的触发一下一个事件。

 

分享到:
评论

相关推荐

    Filter驱动开发笔记

    纵横捭阖C++之从异步谈起 - **异步编程**:一种非阻塞式的编程模型,可以提高程序的响应速度。 - **应用场景**:网络编程、多线程编程等。 #### 38. Windows系统编程之异步I/O和完成端口 - **异步I/O**:允许...

    业务纵横捭阖背后的技术拆分与融合.pdf

    在业务"纵横捭阖"的背后,技术的拆分与融合是确保系统稳定性和灵活性的关键。这个案例主要讨论了在团购电影票、卖品以及衍生品等业务场景下,如何通过技术手段进行系统优化和升级,以适应快速变化的业务需求。 首先...

    大国时代的兴衰史:海权、工业与殖民的纵横捭阖.doc.pdf

    大国时代的兴衰史:海权、工业与殖民的纵横捭阖.doc

    鬼谷子谋略与总裁智慧2.pptx

    纵横捭阖是鬼谷子谋略的核心所在,包括捭阖、反应、内楗、抵巇等多个方面的内容。以下是对鬼谷子谋略与总裁智慧的详细解释: 一、捭阖术 捭阖术是鬼谷子谋略的基础理论,强调了开合的重要性。鬼谷子认为,一开一合...

    mysql-connector-c++-8.0.23-macos10.15-x86-64bit.dmg

    mysql-connector-c++-8.0.23-macos10.15-x86-64bit.dmg

    qt5使用curl实现文件下载的示例程序

    Qt5是一个功能强大的C++开发框架,提供了丰富的API用于构建跨平台的应用程序。同时,cURL是一个广泛使用的命令行工具和库,用于处理各种网络协议,包括HTTP、FTP等。本篇文章将深入探讨如何在Qt5中利用cURL库实现...

    无领导小组面试技巧.pdf

    在无领导小组讨论中,应聘者可能会遇到各种角色,例如纵横捭阖者、天然领导者、时间控制者、细节记录者和总结陈述者等。不同的角色代表了不同的能力和风格,应聘者需要根据自己的性格特点和优势来选择最适合自己的...

    名华慕课国学智慧及应用.docx

    鬼谷子的思想被用来解决处理人与环境、自我、他人之间的复杂关系,教导人们如何在纵横捭阖中成就伟业。 在第一章中,讨论了企业家应具备的素质,包括但不限于领导力、聪敏、明智、勇气和胆识,同时也提到了鬼谷子的...

    诸侯争霸与社会变革.ppt

    "逞干戈,尚游说"描绘了那个时代战争频繁、谋士纵横捭阖的景象。"始春秋,终战国"划分了这一历史时期,春秋时期始于公元前770年,结束于公元前476年,战国时期则从公元前475年开始,直至公元前221年秦统一六国。 ...

    高考易错字音字形归纳.doc

    1. **捭阖**:"纵横捭阖"的"捭阖"常被误写为"拌合"。 2. **裨**:"奴颜婢膝"的"裨"容易误写为"脾"。 3. **薄**:"薄纸"的"薄"与"薄情"的"薄"字形相似,要区分其含义。 4. **差**:"偏差"、"差距"的"差"与"差不多"的...

    新课标语文必修二课本知识点总结精品全.ppt

    - 纵横捭阖:战国时期策士们游说各国的一种策略,通过分化或拉拢来影响政治决策。 - 沮涸辙之鱼:比喻处境困窘,亟需援助的人。 - 终南捷径:借指通过某种简便快捷的方式获得名利或地位。 - 束之高阁:形容将...

    七年级历史上册春秋战国的纷争与社会变化中华书局PPT教案.pptx

    这种纵横捭阖的策略使得战国时期的政治局面更加复杂多变。 军事领域同样取得了显著进展,这一时期涌现出了像孙武和孙膑这样的杰出军事家,他们的著作《孙子兵法》和《孙膑兵法》分别对后世产生了深远的影响。《孙子...

    从春秋战国看中国最早的营销策划.docx

    这些历史人物都是卓越的策划家,他们深刻理解人心,洞悉国家未来的命运,以口才和智谋在各国之间纵横捭阖。 策划一词最早见于《先汉书·隗器传》,意指规划和计算。在当代,营销策划强调以战略为导向,通过精准定位...

    初中语文常见错别字.doc

    5. 纵横捭阖(俾):正确为“捭阖”,形容善于权谋,此处“捭阖”与“俾阖”混淆。 6. 中流砥柱(抵):正确为“砥柱”,比喻坚强的支柱,此处“砥”与“抵”混淆。 7. 脍炙人口(烩):正确为“脍炙”,形容美好的...

    小学生最易读错的字词PPT课件.pptx

    7. "纵横捭阖" (bǎi hé):形容政治或外交上的策略手腕,纵横捭阖地处理复杂关系。 8. "裨官野史" (bài):非正式的、民间的历史记载。 9. "扳平" (bān):在比赛中追平比分。 10. "同胞" (bāo):指同种族、同...

    运维生态链建设探索.pdf

    总的来说,运维生态链建设是通过标准化、组件化和自动化手段,打破业务壁垒,优化资源配置,提高运维效率,实现运维团队从“如履薄冰”到“纵横捭阖”的转变。这一过程不仅关乎技术选型,更关乎运维团队的组织结构、...

    年高一语文上册期中考试试卷.doc

    4. **基础知识**:涵盖词汇、语法、修辞等,如“匍匐”、“纵横捭阖”的解释。 5. **标点符号**:检查学生对标点符号规则的掌握,如问号、逗号、顿号等的正确使用。 这些题目反映了高中阶段语文学习的基本要求,...

    过秦论优秀教(学)案.doc

    通过诵读课文,学生得以初步接触并欣赏到贾谊赋体文的独特魅力——铺张扬厉、纵横捭阖的文风。分组朗读的环节,更使学生在互动中深入体会文章的句式特色,诸如夸张和排比手法的运用,进而增强对文章论点的理解与感受...

    读史使人明智读《中华五千年》有感(2000字).docx.docx

    在这部作品中,我们能够窥见中国五千年文明的辉煌与沉浮,政治的跌宕起伏,经济的兴衰更迭,军事的胜败荣辱,外交的纵横捭阖,科学的进步,艺术的璀璨以及宗教的深邃。这些丰富多彩的内容,不仅为读者展现了一个立体...

Global site tag (gtag.js) - Google Analytics