Windows系统的线程调度与软件中断分发
在Windows操作系统内核把软件中断分为三个中断级别:DISPATCH_LEVEL,APC_LEVEL,PASSVIE_LEVEL。同时他们与线程的调试相关,WINDOWS内核中没有一个专门的程序来做线程的调度工作,它是散落在系统各个部分的。总结一下主要以下几种情况。
当空闲线程运行时粗略讲是1.先检查当前处理的DPC例程队列,分发DPC调用。2.检查NextThread是否为空,如果存在不为空就切换到这个线程,若为空进行第三步3.执行线程的调试算法。
当HalpDispatchSoftwareInterrupt被调用时。这个函数主要流程还是比较简单的,判断了第一个参数是否为1(APC_LEVEL)如果是调用KiDeliverApc来分发APC例程。若不是接看是否为2(DISPATCH_LEVEL),是的话就调用KiDispatchInterrupt。KiDispatchInterrupt这个函数内容较多,不过流程上跟空闲进程差不多。只是它检查了当前处理器的QuantumEnd标记,若不为0就执行KiQuantumEnd,KiQuantumEnd这个函数进行了线程的调试。
hal!HalpDispatchSoftwareInterrupt:
83c1f8c6 8bff mov edi,edi
83c1f8c8 55 push ebp
83c1f8c9 8bec mov ebp,esp
83c1f8cb51 push ecx
83c1f8cc53 push ebx
83c1f8cd56 push esi
83c1f8ce 9c pushfd
83c1f8cf58 pop eax
83c1f8d08945fc mov dword ptr [ebp-4],eax
83c1f8d38b75fc mov esi,dword ptr [ebp-4]
83c1f8d681e600020000 and esi,200h
83c1f8dc 8a4508 mov al,byte ptr [ebp+8]
83c1f8df 64a224000000 mov byte ptr fs:[00000024h],al
83c1f8e57501 jne hal!HalpDispatchSoftwareInterrupt+0x22 (83c1f8e8)
hal!HalpDispatchSoftwareInterrupt+0x21:
83c1f8e7fb sti
hal!HalpDispatchSoftwareInterrupt+0x22:
83c1f8e833db xor ebx,ebx
83c1f8ea381dbd6ac383 cmp byte ptr [hal!HalpEnableIrqlAudit (83c36abd)],bl
83c1f8f0 7405 je hal!HalpDispatchSoftwareInterrupt+0x31 (83c1f8f7)
hal!HalpDispatchSoftwareInterrupt+0x2c:
83c1f8f2e8e9feffff call hal!HalpValidatePendingInterrupts (83c1f7e0)
hal!HalpDispatchSoftwareInterrupt+0x31:
83c1f8f7807d0801 cmp byte ptr [ebp+8],1
83c1f8fb7514 jne hal!HalpDispatchSoftwareInterrupt+0x4b (83c1f911)
hal!HalpDispatchSoftwareInterrupt+0x37:
83c1f8fdff750c push dword ptr [ebp+0Ch]
83c1f90064881d96000000 mov byte ptr fs:[96h],bl
83c1f90753 push ebx
83c1f90853 push ebx
83c1f909ff15e4b0c183 call dword ptr [hal!_imp__KiDeliverApc (83c1b0e4)]
83c1f90f eb1e jmp hal!HalpDispatchSoftwareInterrupt+0x69 (83c1f92f)
hal!HalpDispatchSoftwareInterrupt+0x4b:
83c1f911807d0802 cmp byte ptr [ebp+8],2
83c1f915 750f jne hal!HalpDispatchSoftwareInterrupt+0x60 (83c1f926)
hal!HalpDispatchSoftwareInterrupt+0x51:
83c1f91764881d97000000 mov byte ptr fs:[97h],bl
83c1f91eff15e0b0c183 call dword ptr [hal!_imp__KiDispatchInterrupt (83c1b0e0)]
83c1f924eb09 jmp hal!HalpDispatchSoftwareInterrupt+0x69 (83c1f92f)
hal!HalpDispatchSoftwareInterrupt+0x60:
83c1f926381dbd6ac383 cmp byte ptr [hal!HalpEnableIrqlAudit (83c36abd)],bl
83c1f92c 7401 je hal!HalpDispatchSoftwareInterrupt+0x69 (83c1f92f)
hal!HalpDispatchSoftwareInterrupt+0x68:
83c1f92ecc int 3
hal!HalpDispatchSoftwareInterrupt+0x69:
83c1f92f 3bf3 cmp esi,ebx
83c1f9317501 jne hal!HalpDispatchSoftwareInterrupt+0x6e (83c1f934)
hal!HalpDispatchSoftwareInterrupt+0x6d:
83c1f933fa cli
hal!HalpDispatchSoftwareInterrupt+0x6e:
83c1f934381dbd6ac383 cmp byte ptr [hal!HalpEnableIrqlAudit (83c36abd)],bl
83c1f93a 7411 je hal!HalpDispatchSoftwareInterrupt+0x87 (83c1f94d)
hal!HalpDispatchSoftwareInterrupt+0x76:
83c1f93c 64a024000000 mov al,byte ptr fs:[00000024h]
83c1f942 3a4508 cmp al,byte ptr [ebp+8]
83c1f9457401 je hal!HalpDispatchSoftwareInterrupt+0x82 (83c1f948)
hal!HalpDispatchSoftwareInterrupt+0x81:
83c1f947cc int 3
hal!HalpDispatchSoftwareInterrupt+0x82:
83c1f948e893feffff call hal!HalpValidatePendingInterrupts (83c1f7e0)
hal!HalpDispatchSoftwareInterrupt+0x87:
83c1f94d5e pop esi
83c1f94e5b pop ebx
83c1f94f c9 leave
83c1f950 c20800 ret 8
还有一种情况是当执行了一些等锁或事件等函数时,这时会发生线程切换。这里有一个特殊情况是(Thread->ApcState.KernelApcPending && (Thread->SpecialApcDisable == 0)&& (Thread->WaitIrql < APC_LEVEL))时会进入KiExitDispatcher流程;基本上是先Thread->WaitIrql = KeRaiseIrqlToSynchLevel();InitializeDelayExecution();最后通过KiUnlockDispatcherDatabase(Thread->WaitIrql);调入KiExitDispatcher(\*Thread->WaitIrql*\)中。
8aed3c5883cbe403 00000000 86a3e240ffffffff nt!KiSwapThread+0x254
8aed3c8083cbe0e1 86a3e240 86a3e300 00000044nt!KiCommitThreadWait+0x1df
8aed3cd8 83e826ed 00000201 00000000 8aed3cfcnt!KeDelayExecutionThread+0x2aa
8aed3d24 83c9442a 00000000 00f5f79000f5f7b4 nt!NtDelayExecution+0x8d
8aed3d24 771864f400000000 00f5f790 00f5f7b4 nt!KiFastCallEntry+0x12a (FPO: [0,3] TrapFrame @ 8aed3d34)
00f5f748 77184c1c 753f187600000000 00f5f790 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
00f5f74c 753f187600000000 00f5f790 53ddb789 ntdll!ZwDelayExecution+0xc (FPO:[2,0,0])
00f5f7b4 753f1818 00000064 00000000 00f5f800KERNELBASE!SleepEx+0x65 (FPO: [Non-Fpo])
00f5f7c4 70586be7 00000064 52194086 00000000KERNELBASE!Sleep+0xf (FPO: [Non-Fpo])
00f5f800 70587824 00f5f81476971174 001cea40 MSDTCPRX!CConnectionManager::TimerProcForNonGuardedUser+0x72(FPO: [Non-Fpo])
00f5f808 76971174001cea40 00f5f854 7719b3f5MSDTCPRX!CConnectionManager::TimerProc+0x1e (FPO: [Non-Fpo])
00f5f814 7719b3f5 001cea40 77d42614 00000000kernel32!BaseThreadInitThunk+0xe (FPO: [Non-Fpo])
00f5f854 7719b3c8 70587806 001cea40 00000000ntdll!__RtlUserThreadStart+0x70 (FPO: [Non-Fpo])
00f5f86c 00000000 70587806 001cea40 00000000ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])
PKTHREAD CurrentThread;
PKTHREAD NewThread;
BOOLEAN Pending;
PKPRCB Prcb;
ASSERT(KeGetCurrentIrql() == SYNCH_LEVEL);
//
// Process the deferred ready list if the list is not empty.
//
Prcb = KeGetCurrentPrcb();
#if !defined(NT_UP)
if (Prcb->DeferredReadyListHead.Next != NULL) {
KiProcessDeferredReadyList(Prcb);
}
#endif
//
// If the old IRQL is less than dispatch level, then a new thread can
// be dispatcher immediately.
//
if (OldIrql < DISPATCH_LEVEL) {
//
// If there is a new thread selected for execution, then switch
// context to the new thread.
//
if (Prcb->NextThread != NULL) {
KiAcquirePrcbLock(Prcb);
NewThread = Prcb->NextThread;
CurrentThread =Prcb->CurrentThread;
KiSetContextSwapBusy(CurrentThread);
Prcb->NextThread = NULL;
Prcb->CurrentThread = NewThread;
NewThread->State = Running;
KxQueueReadyThread(CurrentThread,Prcb);
CurrentThread->WaitIrql =OldIrql;
Pending =KiSwapContext(CurrentThread, NewThread);
if (Pending != FALSE) {
KeLowerIrql(APC_LEVEL);
KiDeliverApc(KernelMode, NULL,NULL);
ASSERT(OldIrql == 0);
}
}
} else if ((Prcb->NextThread != NULL) &&
(Prcb->DpcRoutineActive ==FALSE)) {
KiRequestSoftwareInterrupt(DISPATCH_LEVEL);
}
//
// Lower IRQL to its previous level.
//
KeLowerIrql(OldIrql);
return;
HalpDispatchSoftwareInterrupt是调用那这么几种情况:hal!KfLowerIrql调用的时候,有INT3和其它一些中断发现的时候。所以这里有一个问题对HalpDispatchSoftwareInterrupt下一个断点的话,系统的栈溢出了。
可以看出软件中断,基本上是在空闲线程、KiExitDispatcher和HalpDispatchSoftwareInterrupt分被分发的。还有线程切换是DPC级别的,若在DPC级别长时间逗留,会影响线程的切换。
Windows系统的线程调度与软件中断分发的更多相关文章
- Windows系统架构
操作系统模型 大多数操作系统中,都会把应用程序和内核代码分离运行在不同的模式下.内核模式访问系统数据和硬件,应用程序运行在没有特权的模式下(用户模式),只能使用有限的API,且不能直接访问硬件.当 ...
- Windows系统上的.Net版本和.NETFramework的C#版本
前言 注:本文内容摘自维基百科,用于在墙内时当作笔记看. WinForm 需要.Net最低版本 2.0 WPF需要的.Net最低版本 3.0 (Win7及之上版本自带) C#版本 版本 语言规格 日期 ...
- Windows系统通用安全配置基线
一:共享账号检查 配置名称:账号分配检查,避免共享账号存在 配置要求: 1.系统需按照实际用户分配账号: 2.根据系统的使用需求,设定不同的账户和账户组,包括管理员用户,数据库用户,审计用户,来宾用户 ...
- Windows系统的四个重要概念——进程、线程、虚拟内存、内核模式和用户模式
引言 本来在写一篇Windows内存管理的文章,写着写着就发现好多基础的概念都要先讲.更可怕的是,这些基础的概念我却不能完全讲清楚.只好再把这本<深入解析Windows操作系统>翻到第一章 ...
- ssh远程端口转发&&windows系统提权之信息收集&&网安工具分享(部分)
一.ssh远程端口转发 背景:当我们在渗透过程中,获取到内网的一台仅有内网IP的服务器后,我们可以通过ssh隧道,将内网某个主机的端口进行远程转发 1.网络拓扑图 假设获取的服务器为web服务器,we ...
- DOS下windows系统查看wifi密码
DOS下windows系统查看wifi密码 首先,按win+R键,win键如下 弹出框中输入cmd 在弹出界面输入 netsh wlan show profiles 你可以看到你链接过的所有wifi名 ...
- windows系统下fis3安装教程
注意:在安装fis3前必须安装node和npm,详情请见官网http://nodejs.org node版本要求 0.8.x,0.10.x, 0.12.x,4.x,6.x,不在此列表中的版本不予支持. ...
- windows系统快捷操作の高级篇
上次介绍了windows系统上几个比较好用的软件和系统快捷键,虽然有些很方便,但是毕竟还是太少了,而且无法自定义专属于自己的快捷键.所以我写了这么一篇教程,主要介绍两个神器:windows平台上的au ...
- windows系统快捷操作の进阶篇
上次介绍了windows系统上一些自带的常用快捷键,有些确实很方便,也满足了我们的一部分需求.但是我们追求效率的步伐怎会止步于此?这一次我将会进一步介绍windows上提升效率的方法. 一:运行 打开 ...
随机推荐
- 在QTableView中使用各种自定义委托
QT的MVC(View/Delegate)模型十分强大,可以利用各种控件来对表格的输入进行限制,不过我以前一直没有过,这几天研究了一下,写个小例子,希望大家喜欢. 如果看不懂这个例子,请先看QT的自带 ...
- Matalab之模糊KMeans实现
这节继续上节的KMeans进行介绍,上节主要是对模糊KMeans方法的原理做了介绍,没有实践印象总是不深刻,前段时间有个师姐让我帮着写了个模糊KMeans的算法,今天就拿她给出的例子来对这个方法做个实 ...
- Servlet中Web.xml的配置详解
1 定义头和根元素 部署描述符文件就像所有XML文件一样,必须以一个XML头开始.这个头声明可以使用的XML版本并给出文件的字符编码. DOCYTPE声明必须立即出现在此头之后.这个声明告诉服务器适用 ...
- jquery 事件委托三种事件绑定方式.bind(),.live(),.delegate()
http://www.ituring.com.cn/article/467# http://www.cnblogs.com/lvdabao/archive/2013/08/30/3290603.htm ...
- Ruby小例子
1.ruby定义函数与执行函数案例 def fact(n) ) end end print fact() 结果: 24 2.一个小例子 words = [)] print "guess?\n ...
- UML_部署图
一.部署图简介(Deployment Diagram Introduction) 二.部署图元素(Deployment Diagram Elements) 1.结点(Node) 2.结点实例(Node ...
- js LocalStorage
此对象主要有两个方法:保存数据:localStorage.setItem(Key, value);读取数据:localStorage.getItem(Key);Key:表示你要存入的键名称,此名称可以 ...
- HDOJ 4417 - Super Mario 线段树or树状数组离线处理..
题意: 同上 题解: 抓着这题作死的搞~~是因为今天练习赛的一道题.SPOJ KQUERY.直到我用最后一种树状数组通过了HDOJ这题后..交SPOJ的才没超时..看排名...时间能排到11名了..有 ...
- Mysql 多表查询
文章转载的:http://www.cnblogs.com/BeginMan/p/3754322.html 一.Join语法概述 join 用于多表中字段之间的联系,语法如下: ... FROM tab ...
- UVA - 11882 Biggest Number(dfs+bfs+强剪枝)
题目大意:给出一个方格矩阵,矩阵中有数字0~9,任选一个格子为起点,将走过的数字连起来构成一个数,找出最大的那个数,每个格子只能走一次. 题目分析:DFS.剪枝方案:在当前的处境下,找出所有还能到达的 ...