处理器调度程序性能概述
线程支持线程可看作开销低的进程。它是一个可分派实体,创建它需要的资源比创建一个进程需要的资源少。
进程由一个或多个线程组成。事实上,操作系统的早期发行版中负载的直接迁移就是继续创建和管理进程。每个新进程在创建时只带有单一的线程,该线程具有其父进程的优先级并与其它进程中的线程争用处理器。进程在执行时拥有它所使用的资源,而线程仅仅拥有它的当前状态。
当新的或修改的应用程序利用操作系统的线程支持创建额外的线程时,那些线程在该进程的上下文中创建。它们共享进程的私有段和其它资源。
进程中的一个用户线程有一个特定的争用作用域。如果争用作用域是全局的,则该线程与系统中所有其它线程一起争用处理器时间。在进程创建时产生的线程具有全局争用作用域。如果争用作用域本地的,则该线程与进程中的其它线程竞争以成为进程共享的处理器时间的接收方。
决定接下来应该运行哪个线程的算法叫调度策略。
进程和线程进程是系统中的一个活动,它由某个命令、shell 程序或另一进程启动。
进程的属性如下:
pid pgid uid gid环境cwd文件描述符信号操作进程统计信息nice
线程的属性如下:
堆栈调度策略调度优先级暂挂信号阻塞信号线程特定的数据
每个进程由一个或多个线程组成。线程是一个单独的控制序列流。多个控制线程允许应用程序进行重叠操作,例如读取终端和写文件。
多个控制线程也允许应用程序同时为来自多个用户的请求服务。线程提供了这些能力而不需多个进程那样的额外开销,例如要通过 fork() 系统调用创建多个进程。
AIX 4.3.1 中引入了一个快速的 fork 例程 f_fork()。该例程对多线程应用程序非常有用,它们将立刻调用 exec() 子例程,前提是之前应先调用 fork() 子例程。fork() 子例程运行起来较慢,因为在实际派生及让其子例程运行全部子处理程序来初始化所有锁之前,它必须调用 fork 处理程序获得所有的库锁。f_fork() 子例程忽略这些处理程序并直接调用 kfork() 系统调用。Web 服务器是一个可以使用 f_fork() 子例程的很好的应用程序示例。
进程和线程的优先级优先级管理工具处理进程的优先级。在 AIX V4 中,进程优先级只是线程优先级的前驱。当调用 fork() 子例程时,会创建一个进程和一个要在其中运行的线程。线程的优先级归结于进程。
内核为每个线程维护一个优先级值(有时称为调度优先级)。优先级值是一个正整数且与关联线程的重要性的变化方向相反。也就是说,较小的优先级值表示一个相对重要的线程。当调度程序寻找线程进行分派时,它选择具有较小优先级值的可分派线程。
线程可以有固定的优先级或不固定的优先级。优先级固定的线程的优先级值是一个常量,而优先级不固定的线程的优先级值根据用户线程最小优先级级别(常量 40)、线程的 nice 值(缺省值是 20,可随意由 nice 或 renice 命令进行设置)和其处理器使用的损失而变化。
线程的优先级可以固定成某个值,如果用 setpri() 子例程设置(固定)它们的优先级的话,它们可以具有小于 40 的优先级值。这些线程不会受到调度程序重算算法的影响。如果它们的优先级值固定且小于 40,这些线程将在可以运行所有用户线程之前运行和完成。例如,一个具有固定值 10 的线程将在具有固定值 15 的线程之前运行。
用户可以应用 nice 命令使线程的不固定优先级变低。系统管理员可将一个负的 nice 值应用给线程,这样就给了它较好的优先级。
下图显示了一些可以更改优先级值的方法。
图 6. 如何确定优先级值。 插图显示了如何能在执行过程中或应用了 nice 命令之后更改线程调度优先级值。优先级值越小,线程优先级越高。开始时,nice 值缺省为 20 而基本优先级缺省为 40.在执行一些操作及处理器损失后,nice 的值仍为 20 且基本优先级仍为 40.在运行 renice ——5 命令后及使用和以前相同的处理器的情况下,nice 值现在是 15 而基本优先级仍为 40.在以 50 的值发出子例程 setpri() 之后,固定优先级现在是 50 而 nice 值和处理器的使用无关。
线程的 nice 值在创建线程时设置并且在线程的整个生命期中都是常量,除非用户通过 renice 命令或 setpri()、setpriority()、thread_setsched() 或 nice() 系统调用明确更改了它的值。
处理器损失是一个整数,它通过线程最近的处理器使用来计算。如果每次在一个 10 ms 的时钟滴答结束时线程受处理器控制,则最近的处理器使用值近似加 1,直到达到最大值 120.每个滴答的实际优先级损失随着 nice 的值增加。所有线程的最近处理器使用值每秒重算一次。
结果如下:
不固定优先级的线程的优先级随着其最近处理器使用的增加而变低,反之亦然。这暗示一般来讲,某线程最近被分配的时间片越多,则它被分配下一个时间片的可能性越小。
不固定优先级的线程的优先级随着其 nice 值的增加而变低,反之亦然。
注:使用多处理器运行队列及其负载平衡机制以后,nice 或 renice 的值对线程的优先级可能没有预期的影响,因为较低优先级的运行时间可能等于或大于较高优先级的运行时间。要求 nice 或 renice 产生预期效果的线程应该放在全局运行队列中。
可以使用命令 ps 显示进程的优先级值、nice 值和短期的处理器使用值。
请参阅「处理器的控制争用」中对使用 nice 和 renice 命令的更详细的讨论。
请参阅「调谐线程优先级值的计算」,里面有处理器损失计算和最近处理器使用值衰减的详细信息。
优先级机制也用于 AIX 工作负载管理器中来加强处理器资源管理。因为在工作负载管理器下分类的线程具有的优先级由工作负载管理器管理,它们可能与没有在工作负载管理器下分类的线程具有不同的优先级行为。
线程的调度策略下面是线程调度策略的可能值:
SCHED_FIFO这种策略的线程被调度后,它会一直运行到结束,除非被阻塞或有一个较高优先级的线程可分派,它将自愿服从处理器的控制。只有固定优先级的线程才能有 SCHED_FIFO 调度策略。
SCHED_RR当一个 SCHED_RR 线程在时间片的末尾有控制权时,它将移动到和它具有相同优先级的可分派线程队列的尾部。只有固定优先级的线程才能有 SCHED_RR 的调度策略。
SCHED_OTHER这个策略在“POSIX 标准 1003.4a”中作为定义的执行程序进行定义。在每个时钟中断时重算运行线程的优先级值意味着该线程可能失去控制权,因为它的优先级值已经超过了另一可分派线程的优先级值。
SCHED_FIFO2该策略和 SCHED_FIFO 相同,只是它允许一个仅睡眠了很短时间的线程在被唤醒时可放置在其运行队列的头部。这个时间周期是相似性限制(可用 schedtune -a 进行调节)。该策略仅可用于 AIX 4.3.3 及其后续版本。
SCHED_FIFO3调度策略设置成 SCHED_FIFO3 的线程总是放置在运行队列的头部。为了防止属于 SCHED_FIFO2 调度策略的线程放置在 SCHED_FIFO3 之前,当 SCHED_FIFO3 线程入队列时更改运行队列参数,这样属于 SCHED_FIFO2 的线程就不满足使其能够加入运行队列头部时必须满足的标准。该策略仅可用于 AIX 4.3.3 及其后续版本。
SCHED_FIFO4只要优先级值相差 1,较高优先级的 SCHED_FIFO4 调度类线程就不会抢占当前正运行的低优先级线程。缺省行为是当前运行于某给定 CPU 的低优先级线程被有资格在同一 CPU 上运行的高优先级线程抢占。该策略仅可用于 AIX 5L V5100-01 + APAR IY22854 及其后续版本。
调度策略可用系统调用 thread_setsched() 进行设置并且仅对调用线程有效。然而,通过指定进程标识发出 setpri() 调用可将线程设置成 SCHED_RR 调度策略;setpri() 的调用者和 setpri() 的目标不必匹配。
只有那些具有 root 权限的进程可以发出 setpri() 系统调用。只有那些具有 root 权限的线程可将调度策略更改成任何 SCHED_FIFO 选项或 SCHED_RR.如果调度策略是 SCHED_OTHER,则优先级参数被 thread_setsched()子例程忽略。
线程的主要优点是适用于当前由多个异步进程组成的应用程序。这些应用程序可通过转变成多线程结构使得系统中有较轻的负载。
调度程序运行队列调度程序维护一个所有就绪等待分派的线程的运行队列。
给定优先级的所有可分派线程在运行队列中占有一定的位置。
调度程序的基本可分派实体是线程。AIX 5.1 维护 256 个运行队列(128 个在 AIX 4.3 及以前的发行版中)。在 AIX 5.1 中,运行队列与每个线程优先级字段可能值的范围(从 0 到 255)直接相关。这个方法使调度程序更容易确定哪个线程最先运行。调度程序无需搜索一个完整的运行队列,只需要考虑一个掩码,该掩码的某一位启用后可表示在相应的运行队列中存在就绪等待运行的线程。
线程的优先级值快速而频繁地变更。持续的变动归因于调度程序重算优先级的方法。然而,这并不适用于固定优先级的线程。
从 AIX 4.3.3 开始,每个处理器都有自己的运行队列。性能工具中报告的运行队列值将是每个运行队列中所有线程的总和。让每个处理器都有自己的运行队列可节省分派锁的开销并改善总体的处理器相似性。线程通常会更加趋向于留在同一处理器中。如果因为另一处理器上的事件使某线程变得可运行且有空闲的处理器的话,即使不同于最近可运行线程曾经运行过的处理器,该线程也只会立即被分派。在可以检查处理器状态(例如在该线程的处理器上的中断)之前不会出现抢占。
在具有多个运行队列的多处理器系统中,可能出现瞬间的优先级倒置。在任何一个时间点都可能出现这种情况:某个运行队列能使若干线程具有的优先级比另一运行队列更有利。AIX 有一些机制可以随着时间的推移来进行优先级平衡,但是如果要求严格的优先级(例如,对于实时应用程序)可用一个叫做 RT_GRQ 的环境变量,如果将它设置成 ON,将导致该线程位于一个全局运行队列中。在那种情况下,将搜索全局运行队列来察看哪个线程具有最佳优先级。这可以改善中断驱动线程的性能。如果将 schedtune -F 设置成 1,以固定优先级运行的线程就放置在全局运行队列中。
运行队列中的线程平均数可在命令 vmstat 输出的第一列中看到。如果用处理器数去除这个数,结果是每个处理器上可运行线程的平均数。如果这个值大于 1,这些线程必须等待轮到它们使用处理器(这个数越大,性能延迟可能越明显)。
当某线程移到运行队列的末端时(例如,当线程在时间片的末尾拥有控制权时),它会移动到具有相同优先级值的队列中最后一个线程之后的位置上。
调度程序处理器时间片处理器时间片是调度程序转换到另一个具有相同优先级的线程之前,一个 SCHED_RR 线程能获得的时间的总和。可以使用命令 schedtune 的选项 -t 在时间片上以 10 毫秒的增量来增加时钟滴答数(参阅「用 schedtune 命令修改调度程序时间片」)。
注:时间片并不是保证的处理器时间量。它是一个线程在面临由另一线程取代的可能性之前可以受控的最长时间。在控制时间达到完整时间片之前有很多方法可使线程失去处理器的控制。
方式转换用户进程在需要访问系统资源时会经历一个方式转换。这通过系统调用接口或诸如缺页故障这样的中断来实现。有两种方式:
用户方式内核方式花在用户方式(应用程序和共享库)下的处理器时间作为用户时间在一些命令的输出中反映出来,例如,vmstat、iostat 和 sar 命令。花在内核方式下的处理器时间作为系统时间在这些命令的输出中反映出来。
用户方式在用户保护域中执行的程序是用户进程。在这种保护域中执行的代码以用户执行方式执行,且具有下列访问:
读/写访问进程专用区域中的用户数据读访问用户文本和共享文本区域使用共享内存功能访问共享数据区域在用户保护域中执行的程序不能访问内核或内核数据段,除非通过使用系统调用间接访问。在该保护域中的程序只能影响自身的执行环境并在进程或非特权状态下执行。
内核方式在内核保护域中执行的程序包含中断处理程序、内核进程、基内核和内核扩展(设备驱动程序、系统调用和文件系统)。这个保护域暗示以内核执行方式执行代码,具有下列访问:
读/写访问全局内核地址空间在进程中执行时读/写访问进程区域中的内核数据内核服务必须用来访问进程地址空间中的用户数据。
在该保护域中执行的程序会影响所有程序的执行环境,因为它们具有下列特征:
它们可访问全局系统数据它们可使用内核服务它们免受所有安全性约束它们执行于处理器特权状态下。
方式转换用户方式的进程使用的系统调用允许通过用户方式调用内核函数。直接或间接地调用系统调用来访问的函数一般由程序设计库提供,它们提供对操作系统函数的访问。
方式转换应该不同于在命令 vmstat(cs 列)和 sar(cswch/s)的输出中所看到的上下文转换。在当前运行的线程不同于该处理器上先前运行的线程时会出现上下文转换。
当下列任一情况出现时调度程序执行上下文转换:
线程必须等候某个资源(自愿),比如磁盘 I/O、网络 I/O、睡眠或锁一个较高优先级线程被唤醒(非自愿)
线程已经用完了它的时间片(通常是 10 ms)。
上下文转换的时间、系统调用、设备中断、NFS I/O 和内核中任何其它活动都看作系统时间。
2004-8-23 19:48:39 鲜花(0) 鸡蛋(0)
snappyboy
等级:论坛游民文章:123积分:283注册:2003-10-20第2楼
多处理介绍无论何时,单处理器芯片的运行速度都存在着技术上的限制。如果单处理器无法令人满意地处理系统的工作负载,一种响应是使用多处理器来解决这个问题。
这种响应是否成功不仅仅取决于系统设计者的技术熟练程度,还取决于工作负载是否服从多处理控制。就人的任务而言,如果任务是应答一个免费电话号码的呼叫,增加人员也许不失为一个好主意,但是假如任务是开车的话,这种做法是否有效就值得怀疑了。
如果建议从一个单处理器系统迁移到一个多处理器系统的目标是为了改进性能,则下列条件必须成立:
工作负载受处理器限制并且已经使得它的单处理器系统饱和。
工作负载包含多种处理器密集的元素,例如事务或者复杂计算,这些操作可以同时并且各自独立地执行。
现有的单处理器不能升级,也不能由另一个能量充足的单处理器代替。
虽然正常情况下不变的单线程应用程序在某个多处理器环境中能正确运行,但它们的性能常常会有意外的变化。迁移到多处理器可以改善系统的吞吐量,并能改进复杂的多线程应用程序的执行时间,但是很少能改进个别的单线程命令的响应时间。
要从一个多处理器系统获得最佳性能,需要对多处理器系统独有的操作系统和硬件执行动态有所了解
对称多处理器(SMP)概念和体系结构对于增加系统复杂性的任何变化,为了获得令人满意的操作和性能,使用多处理器产生了一些设计时必须引起注意的事项。额外的复杂性使得软/硬件权衡的作用域更大,并且比在单处理器系统中更需要软/硬件的密切配合。设计响应和权衡的不同组合使得多处理器系统的体系结构更加多样化。
这一节描述了多处理器系统的主要设计注意事项和这些事项的硬件响应。
多处理的类型有几种多处理(MP)系统,如下所述:
非共享 MP(纯群集)
每个处理器都是一个完全独立的机器,运行操作系统的一个副本。处理器之间没有共享的部分(每一个都有自己的内存,高速缓存和磁盘),但是它们是互联的。通过 LAN 连接时,处理器之间是松散耦合的。而通过转换器连接时,处理器之间是紧密耦合的。处理器之间的通信是通过消息传送来实现的。
这样一个系统的优点是它具有很好的可伸缩性和高可用性。而缺点则是该系统是一个不为人熟悉的编程模型(消息传送)。
共享磁盘 MP处理器拥有自身的内存和高速缓存。处理器并行运行并共享磁盘。每个处理器都运行操作系统的一份副本,并且处理器之间是松散耦合的(通过 LAN 连接)。处理器之间的通信是通过信息传送实现的。
共享磁盘的优点是保留了熟悉的编程模型的一部分(磁盘数据是可寻址和连续的,而内存则不是),而且与共享内存的系统相比,这种系统更容易实现高可用性。缺点是由于在对共享数据进行物理和逻辑访问时存在瓶颈,它的可伸缩性受到限制。