Windows Internals 笔记——线程优先级
1.每个线程都被赋予0(最低)~31(最高)的优先级数。当系统确定给哪个线程分配CPU时,它会首先查看优先级为31的线程,并以循环的方式进行调度。如果有优先级为31的线程可供调度,那么系统就会将CPU分配给该线程。在该线程的时间片结束时,系统查看是否还存在另一个优先级为31的线程可以运行,如果存在,它将获得CPU。
2.只要有优先级为31的线程可供调度,系统就不会给优先级0~30的线程分配CPU。这种情况称为饥饿。在多处理器机器上饥饿发生的可能性要小得多,因为这种机器上优先级为31和30的线程可以同时运行。
3.较高优先级的线程总是会抢占较低优先级的线程,无论较低优先级的线程是否正在执行。系统确定有较高优先级的线程已经准备好可以运行时,它会立即暂停较低优先级的线程(即使后者的时间片还没有用完),并将CPU分配给较高优先级的线程,该线程获得一个完整的时间片。
4.系统启动时,将创建一个名为页面清零线程的特殊线程。这个线程的优先级定为0,而且是整个系统中唯一一个优先级为0的线程。页面清零线程负责在没有其他进程需要执行的时候,将系统内存中的所有闲置页面清零。
5.Windows API在系统的调度程序之上提供了一个抽象层,因此我们不会直接调度调度程序,相反,调用的是Windows函数,它们会根据底层操作系统的版本来解释参数。
6.Windows支持6个优先级类:

- idle优先级类非常适合只在系统什么都不做的时候运行的应用程序。
- 只有在绝对必要的时候才使用high优先级。应该尽可能避免使用real-time优先级类,因为大多数操作系统线程在执行时所用的优先级类都比它低。
- 99%的进程都是normal优先级类。
- 进程不能运行在real-time优先级类,除非用户有Increase Scheduling Priority特权。默认情况下,隶属于管理员或者高级用户组的用户都具有这一权限。
7.Windows支持7个相对线程优先级,这些优先级是相对于进程优先级的。同样,大多数线程使用normal优先级。

8.概括起来,进程都属于某个优先级类,另外还可以指定进程中线程的相对线程优先级。 在不同版本的操作系统上映射(对应到0~31)是变化的。如下表是Windows Vista上的具体情况。

9.优先级0是保留给页面清零线程。除此之外,应用程序也无法获得一下优先级:17,18,19,20,21,27,28,29,30。但是如果编写的是运行在内核模式的设备驱动程序,那么我们可以获得这些优先级。用户模式的应用程序是不能获得这些优先级的。
10.real-time优先级类的线程,其优先级值不能低于16。同理,非real-time优先级线程的优先级的优先级值不能高于15。
11.一般而言,有较高优先级的线程大多数时候都应是不可调度的,当这种线程要执行什么任务时,很快就能得到CPU时间。这时,线程应该尽可能少地执行CPU指令,并重新进入睡眠,等待再次被调度。相反,优先级低的可以保持为可调度状态,执行大量CPU指令以完成其任务。
12.调用CreateProcess时,可以在fdwCreate参数中传入需要的优先级。

13.一旦进程运行,可以调用SetPriorityClass来改变自己的优先级。GetPrioirityClass来获取进程优先级。
14.通过命令行界面调用程序时,程序的起始优先级时normal。但是,如果使用START命令调用程序,可以使用一个开关指定程序的起始优先级。例如:
C:\WINDOWS\system32>START /LOW CALC.EXE
15.CreateThread函数没有为调用者提供设置新线程相对优先级的办法。为了设置和获取线程的相对优先级,必须调用SetThreadPriority和GetThreadPriority函数。
16.CreateThread总是创建相对线程优先级为normal的新线程。要使线程以idle优先级执行,我们需要在调用CreateThead上传入CREATE_SUSPENDED标志,这将阻止线程执行任何代码。然后调用SetThreadPriority将线程改为idle相对线程优先级。接着调用ResumeThread,线程就成为可调度的了。
17.Windows并没有提供返回线程优先级的函数,因为Microsoft保留了任何时候改变调度算法的权力。
18.偶尔,系统也会提升一个线程的优先级,通常时为了响应某种I/O事件,比如窗口消息或磁盘读取。例如:
- high优先级进程中的一个线程优先级为normal的线程,其基本优先级值为13.如果用户敲一个键,系统会在线程的队列中放入一个WM_KEYDOWN消息。因为有消息出现在线程的队列中,线程就成为可调度的了。而且,键盘设备驱动程序将使用系统临时提升线程的优先级。因此线程的优先级可能会提升2,从而达到15。
- 线程在优先级为15时分得一个时间片。在该时间片结束之后系统将线程的优先级值减1,所以在下一个时间片中线程的优先级将为14.线程的第三个时间片以优先级13执行。以后的时间片将保持在13,即线程的基本优先级。
注意,线程的当前优先级不会低于线程的基本优先级。而且使线程可调度的设备驱动程序能够决定提升的幅度,同样,Microsoft也没有在文档中记录任何一个设备驱动程序能够将线程的优先级提升多少。因此,Microsoft可以不断地微调动态提升,以确定最佳的总体响应性。
19.系统只提升优先级值在1~15的线程。这个范围被称为动态优先级范围。而且,系统不会吧线程的优先级提升到实施范围(高于15)。系统也不能动态提升实时范围(16~31)的线程。
20.Microsoft增加SetProcessPriorityBoost和SetThreadPriorityBoost两个函数,允许我们禁止系统对线程优先级进行动态提升。GetProcessPriorityBoost和GetThreadPriorityBoost来查询。
21.当系统检测到有线程已经处于饥饿状态3到4秒,它会动态将饥饿线程的优先级提升到15,并允许该线程运行两个时间片。当两个时间片结束时,线程的优先级立即恢复到基本优先级。
22.如果用户需要使用某个进程的窗口,这个进程就称为前台进程,所有其他进程称为后台进程。为了改进前台进程的响应性,Windows会为前台进程中的现初微调调度算法。系统给前台进程的线程分配比一般情况下更多的时间片。这种微调只在前台进程是normal优先级时才进行。如果处于其他优先级,则不会进行微调。
23.从Windows Vista开始,线程可以在进行I/O请求时设置优先级。我们可以通过调研SetThreadPriority并传入THREAD_MODE_BACKGROUND_BEGIN来告诉Windows,线程应该发送低优先级的I/O请求。注意,这也将降低线程的CPU调度优先级。我们可以通过调用SetThreadPriority并传入THREAD_MODE_BACKGROUND_END,让线程进行normal优先级I/O的请求。系统不允许线程改变另一个线程的I/O优先级。
24.如果想让进程中的所有线程都进行低优先级的I/O请求和低CPU调度,那么我们可以调用SetPriorityClass,传入THREAD_MODE_BACKGROUND_BEGIN标志,相反则传入THREAD_MODE_BACKGROUND_END。
25.在更细的粒度上,normal优先级线程还可以执行对某个文件执行后台优先级I/O。例如SetFileInformationByHandle设置的优先级将覆盖进程的优先级或线程。
26.如果一个low优先级线程获得了normal优先级线程等待的锁,则normal优先级线程可以在低优先级I/O请求完成之前运行,不等待后台优先级线程。后台优先级线程甚至不再进行I/O,以免出现问题。因此,应该尽量减少在normal和后台优先级线程之间使用共享同步对象,以避免normal优先级线程为后台优先级线程拥有的锁而被阻塞,导致优先级逆转。
Windows Internals 笔记——线程优先级的更多相关文章
- Windows Internals 笔记——线程
1.进程有两个组成部分,一个进程内核对象和一个地址空间.线程也有两个组成部分: 一个是线程的内核对象,操作系统用它管理线程.系统还用内核对象来存放线程统计信息的地方. 一个线程栈,用于维护线程执行时所 ...
- Windows Internals 笔记——线程局部存储区
1.由于C/C++运行库是在多线程应用程序出现的许多年前设计的,因此运行库中的大多数函数是为单线程应用程序设计的. 2.当应用程序第一次调用_tcstok_s的时候该函数将传入的字符串地址保存在它自己 ...
- <<Windows via C/C++>>学习笔记 —— 线程优先级【转】
转自:http://www.cnblogs.com/wz19860913/archive/2008/08/04/1259807.html 每个线程都有一个“优先级”,范围是0-31,0为最低优先级,3 ...
- Windows Internals 笔记——关联性
1.默认情况下,Windows Vista在给线程分配处理器时,使用软关联.意思是如果其他因素都一样,系统将使线程在上一次运行的处理器上运行.让线程始终在同一个处理器上运行有助于重用仍在处理器高速缓存 ...
- Windows Internals 笔记——线程调度
1.线程内核对象中的CONTEXT反应了线程上一次执行时CPU寄存器的状态.大约每隔20ms,Windows都会查看所有当前存在的线程内核对象.Windows在可调度的线程内核对象中选择一个,并将上次 ...
- Windows Internals 笔记——CreateProcess
1.一个线程调用CreateProcess时,系统将创建一个进程内核对象,其初始使用计数为1.然后系统为新进程的主线程创建一个线程内核对象(使其计数为1). 2.CreateProcess在进程完全初 ...
- Windows Internals 笔记——进程
1.一般将进程定义成一个正在运行的程序的一个实例,由以下两部分构成: 一个内核对象,操作系统用它来管理进程,内核对象也是系统保存进程统计信息的地方. 一个地址空间,其中包含所有可执行文件或DLL模块的 ...
- Windows Internals 笔记——错误处理
1.Windows函数检测到错误时,会使用一种名为“线程本地存储区”的机制将相应的错误代码与“主调线程”关联到一起.这种机制使得不同的线程能独立运行,不会出现相互干扰对方的错误代码的情况. 2.Get ...
- Windows Internals 笔记——进程的权限
1.大多数用户都用一个管理员账户来登录Windows,在Vista之前,这样的登录会创建一个安全令牌.每当有代码试图使用一个受保护的安全资源时,操作系统就会出示这个令牌.从包括Windows资源管理器 ...
随机推荐
- 《AutoCAD Civil 3D .NET二次开发》勘误2
4.6.3节中代码: 原代码: 06 pdo.Keywords.Add("Pi", "Pi", "派<Pi>"); 07 pdo ...
- gd.so和php_gd2.so 有什么区别
1.关于gd与gd2有什么区别,可以参加以下的链接,简单来说gd2就是gd的更新版,可以处理更多图像类型 https://stackoverflow.com/questions/3035216/wha ...
- 关于Vue修改默认的build文件存放的dist路径
原文地址:http://www.cnblogs.com/JimmyBright/p/7681086.html Vue默认build路径是项目的dist目录下,有时候我们可能希望build之后的文件自动 ...
- MySQL学习基础知识1
什么是数据库? 数据库就是存储数据的仓库. 存储方式: 变量 无法永久存储 文件处理,可以永久存储,弊端:文件只能在自己的计算机读写,无法被分享(局域网除外) 数据库分类: 1.关系型数据库 提供某种 ...
- 树莓派wiringPi,BCM,BOARD编码对应管脚
wiringPi,BCM,BOARD编码 由于上课需要, 嵌入式学习从树莓派开始 树莓派中执行: $> gpio readall 即可得到关于树莓派管脚的各种信息 上面的图可能不是特别清楚, 可 ...
- CF 1145 (愚人节比赛)
D题 题目就是让你找出题面中拼错的单词,拼错的字母组合成一句话就是正确的题面. two plus xor of third and min elements #include<bits/stdc ...
- 001 UI介绍
UI全称:User Interface,即用户界面 UI的职责:负责人机之间的交互,它需要将关键信息,操作逻辑等展示给用户 UI在游戏中承担的职责: 1.游戏美术风格的重要组成部分 2.承担着重要的美 ...
- ModBus-RTU详解
Modbus 一个工业上常用的通讯协议.一种通讯约定.Modbus协议包括RTU.ASCII.TCP.其中MODBUS-RTU最常用,比较简单,在单片机上很容易实现.虽然RTU比较简单,但是看协议 ...
- [面试] Java GC (未整理完)
Java GC简介 什么是 GC ? Java程序不用像C++程序在程序中自行处理内存的回收释放.这是因为Java在JVM虚拟机上增加了垃圾回收(GC)机制,用以在合适的时间触发垃圾回收. 你都了解哪 ...
- Dynamic Clock in Terminal.
#!/bin/bash tput civis while [ 1 ] do tput clear # tput cup 10 20 info=$(date "+%Y-%m-%d %H:%M: ...