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 笔记——线程优先级的更多相关文章

  1. Windows Internals 笔记——线程

    1.进程有两个组成部分,一个进程内核对象和一个地址空间.线程也有两个组成部分: 一个是线程的内核对象,操作系统用它管理线程.系统还用内核对象来存放线程统计信息的地方. 一个线程栈,用于维护线程执行时所 ...

  2. Windows Internals 笔记——线程局部存储区

    1.由于C/C++运行库是在多线程应用程序出现的许多年前设计的,因此运行库中的大多数函数是为单线程应用程序设计的. 2.当应用程序第一次调用_tcstok_s的时候该函数将传入的字符串地址保存在它自己 ...

  3. <<Windows via C/C++>>学习笔记 —— 线程优先级【转】

    转自:http://www.cnblogs.com/wz19860913/archive/2008/08/04/1259807.html 每个线程都有一个“优先级”,范围是0-31,0为最低优先级,3 ...

  4. Windows Internals 笔记——关联性

    1.默认情况下,Windows Vista在给线程分配处理器时,使用软关联.意思是如果其他因素都一样,系统将使线程在上一次运行的处理器上运行.让线程始终在同一个处理器上运行有助于重用仍在处理器高速缓存 ...

  5. Windows Internals 笔记——线程调度

    1.线程内核对象中的CONTEXT反应了线程上一次执行时CPU寄存器的状态.大约每隔20ms,Windows都会查看所有当前存在的线程内核对象.Windows在可调度的线程内核对象中选择一个,并将上次 ...

  6. Windows Internals 笔记——CreateProcess

    1.一个线程调用CreateProcess时,系统将创建一个进程内核对象,其初始使用计数为1.然后系统为新进程的主线程创建一个线程内核对象(使其计数为1). 2.CreateProcess在进程完全初 ...

  7. Windows Internals 笔记——进程

    1.一般将进程定义成一个正在运行的程序的一个实例,由以下两部分构成: 一个内核对象,操作系统用它来管理进程,内核对象也是系统保存进程统计信息的地方. 一个地址空间,其中包含所有可执行文件或DLL模块的 ...

  8. Windows Internals 笔记——错误处理

    1.Windows函数检测到错误时,会使用一种名为“线程本地存储区”的机制将相应的错误代码与“主调线程”关联到一起.这种机制使得不同的线程能独立运行,不会出现相互干扰对方的错误代码的情况. 2.Get ...

  9. Windows Internals 笔记——进程的权限

    1.大多数用户都用一个管理员账户来登录Windows,在Vista之前,这样的登录会创建一个安全令牌.每当有代码试图使用一个受保护的安全资源时,操作系统就会出示这个令牌.从包括Windows资源管理器 ...

随机推荐

  1. HDU 1757 A Simple Math Problem (矩阵快速幂)

    题目 A Simple Math Problem 解析 矩阵快速幂模板题 构造矩阵 \[\begin{bmatrix}a_0&a_1&a_2&a_3&a_4&a ...

  2. MySQ数据备份

    MySQL备份概述 问题:备份和冗余有什么区别? 备份:能够防止由于机械故障以及人为操作带来的数据丢失,例如将数据库文件保存在了其它地方. 冗余:数据有多份冗余,但不等于备份,只能防止机械故障带来的数 ...

  3. 20165223《网络对抗技术》Exp1 PC平台逆向破解

    目录--PC平台逆向破解 1 逆向及BOF基础实践说明 1.1 实践内容 1.2 实践要求 1.3 基础知识 2 实验步骤 2.1 直接修改程序机器指令,改变程序执行流程 2.2 通过构造输入参数,造 ...

  4. Java基础 -- 持有对象(容器)

    一 容器的用途 如果对象的数量与生命周期都是固定的,自然我们也就不需要很复杂的数据结构. 我们可以通过创建引用来持有对象,如 Class clazz; 也可以通过数组来持有多个对象,如 Class[] ...

  5. [Bzoj 2956] 模积和 (整除分块)

    整除分块 一般形式:\(\sum_{i = 1}^n \lfloor \frac{n}{i} \rfloor * f(i)\). 需要一种高效求得函数 \(f(i)\) 的前缀和的方法,比如等差等比数 ...

  6. sigaction 的使用

    linux内核会发射一些信号,应用程序可以捕捉信号执行特定函数 :失败:-,设置errno act:传入参数,新的处理方式.oldact:传出参数,旧的处理方式. struct sigaction结构 ...

  7. 二、Tensorflow的作用域和图

    作用域主要用来不用重复定义变量,另外就是用与画图 import tensorflow as tf ''' 可视化 tf.summary.scalar 添加一个标量 tf.summary.audio 添 ...

  8. IPv6 RIPng (PT)

    在Cisco路由器上配置RIPng  一.拓扑图 二.地址表 Device Interface IPv6 Address R1 F 0/0 2001:0DB8:CAFE:0001::1/64 S 0/ ...

  9. 整理一些vue elementui 问题 + 链接方法

    1.前端通过spark-md5.js计算本地文件md5 2.vue如何利用自定义的事件,在子组件中修改父组件里边的值 3.vue子组件获取父组件的内容(props属性) 4.Element ui se ...

  10. 扩展欧几里得(exgcd)与同余详解

    exgcd入门以及同余基础 gcd,欧几里得的智慧结晶,信息竞赛的重要算法,数论的...(编不下去了 讲exgcd之前,我们先普及一下同余的性质: 若,那么 若,,且p1,p2互质, 有了这三个式子, ...