线程的调度,优先级和亲缘性

           首先说明下WINDOWS是一个强占式的操作系统 ,WINDOWS会每隔20MS左右就查看线程内核对象,找出某个优先级高的可调度线程进行执行,并将内核对象中的上下文放置到CPU寄存器中。还有一种操作系统是实时性的,比如LINUX,意思是能够让某个线程在特定时间运行,运行多久,但是这种操作系统要求明确的知道它在什么硬件上运行。而WINDOWS是被设计成能在各种不同的硬件上运行,所以WINDOWS不是实时的。

1.暂停和恢复线程运行

 

  • 暂停线程运行:DWORD SuspendThread(HANDLE  hThread)

 

这个函数要小心使用。因为会发生死锁或者线程同步的问题。这里顺便说下暂停进程运行。暂停进程运行不是一件容易的事,因为暂停进程意味着暂停进程中所有线程,而在暂停进程中某个线程的时候很可能发生有另一个线程创建了一个新的线程,而这个新的线程,你的程序将一无所知,所以你暂停不了它。这样很可能导致进程的数据破坏

    • 睡眠线程:VOID Sleep(DWORD dwMilliseconds)

调用这个函数可使线程暂停自己的运行,知道dwMilliseconds过去为止。调用这个函数会发生:

  • 使线程自愿放弃拥有的时间片
  • 系统将在大约的指定毫秒数内使线程不可调度。不错,如果告诉系统,想睡眠100ms,那么可以睡眠大约这么长时间,但是也可能睡眠数秒钟或者数分钟。记住, Wi n d o w s不是个实时操作系统。虽然线程可能在规定的时间被唤醒,但是它能否做到,取决于系统中还有什么操作正在进行。
  • 可以调用S l e e p,并且为d w M i l l i s e c o n d s参数传递I N F I N I T E。这将告诉系统永远不要调度该线程。这不是一件值得去做的事情。最好是让线程退出,并还原它的堆栈和内核对象。
  • 可以将0传递给S l e e p。这将告诉系统,调用线程将释放剩余的时间片,并迫使系统调度另一个线程。但是,系统可以对刚刚调用S l e e p的线程重新调度。如果不存在多个拥有相同优先级的可调度线程,就会出现这种情况。
    • 转换到另一个线程: BOOL SwitchToThread()
    • 计算线程/进程的运行时间可以调用GetThreadTime/GetProcessTime。详细见MSDN

2.关于环境结构CONTEXT。CONTEXT结构其实是记录着CPU的寄存器的信息。因为是和CPU直接接触,所以说CONTEXT结构其实是特定于CPU的。CONTEXT结构分为几个部分。CONTEXT_CONTROL包含C P U的控制寄存器,比如指令指针、堆栈指针、标志和函数返回地址。C O N T E X T _ I N T E G E R用于标识C P U的整数寄存器。C O N T E X T _ F L O AT I N G _ P O I N T用于标识C P U的浮点寄存器。C O N T E X T _ S E G M E N T S用于标识C P U的段寄存器(仅为x 8 6处理器)。CONTEXT_DEBUG_ REGISTER用于标识C P U的调试寄存器(仅为x 8 6处理器)。CONTEXT_EXTENDED_ REGISTERS用于标识C P U的扩展寄存器(仅为x 8 6处理器)。

BOOL GetThreadContext(HANDLE hThread,PCONTEXT pContext)可以得到当前CPU的状况

plus:在调用这个函数之前最好SuspandThread。还有就是要初始化Context.ContextFlag成员,告诉函数你想得到哪些Context。这个值可以设置为CONTEXT_CONTROL,CONTEXT_FULL等。

CPU TypeDefinition of CONTEXT_FULL
x86CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS
AlphaCONTEXT_CONTROL | CONTEXT_FLOATING_POINT | CONTEXT_INTEGER

同样的,通过调用SetThreadContext来设置CPU的寄存器值

3。线程的优先级。

 WINDOWS中每个线程都被赋予予一个从0(最低)到3 1(最高)的优先级号码。WINDOWS还提出了一个新概念就是优先级类,这个类是和进程联系起来的。优先级类有5种:

Priority ClassDescription
Real-timeThe threads in this process must respond immediately to events in order to execute time-critical tasks. Threads in this process also preempt operating system components. Use this priority class with extreme caution.
HighThe threads in this process must respond immediately to events in order to execute time-critical tasks. The Task Manager runs at this class so a user can kill runaway processes.
Above normalThe threads in this process run between the normal and high priority classes (new in Windows 2000).
NormalThe threads in this process have no special scheduling needs.
Below normalThe threads in this process run between the normal and idle priority classes (new in Windows 2000).
IdleThe threads in this process run when the system is otherwise idle. This process is typically used by screensavers or background utility and statistic-gathering software.

 还有一个概念就是相对线程优先级。顾名思义就是某个线程相对与进程优先级类的优先级别,也有5种:

Relative Thread PriorityDescription
Time-criticalThread runs at 31 for the real-time priority class and at 15 for all other priority classes.
HighestThread runs two levels above normal.
Above normalThread runs one level above normal.
NormalThread runs normally for the process's priority class.
Below normalThread runs one level below normal.
LowestThread runs two levels below normal.
IdleThread runs at 16 for the real-time priority class and at 1 for all other priority classes.

那么WINDOWS为什么不直接让程序员给他们的线程设置优先级别呢?比如15,20。原因是随着时代的发展,用户对应用程序的要求也是要改变的,所以优先级不能一成不变。比如以前对3D类程序就不分配高的优先级,因为那个时候大家对3D的效果不需要太高,而现在随着游戏的发展,3D也成了OS用户迫切需要的,而且要求OS处理的很好。所以,WINDOWS为了让自己的具有更高的维护性,就给用户程序员提供了抽象的优先级类,以便以后的WINDOWS的维护方便。

设置程序的优先级有以下几种方法:

  • 设置进程优先级
    • BOOL SetPriorityClass(HANDLE hThread,DWORD fdwPriority)
    • 将CreateProcess的fdwCreate参数传递需要的优先级类。这些优先级类的宏这些:
  • 设置线程的相对优先级
    •  BOOL SetThreadPriority(HANDLE hThread,int nPriority)

下面把进程优先级类和线程相对优先级宏列出来:

 

Priority Class

Symbolic Identifiers
Real-timeREALTIME_PRIORITY_CLASS
HighHIGH_PRIORITY_CLASS
Above normalABOVE_NORMAL_PRIORITY_CLASS
NormalNORMAL_PRIORITY_CLASS
Below normalBELOW_NORMAL_PRIORITY_CLASS
IdleIDLE_PRIORITY_CLASS

 

Relative Thread Priority

Symbolic Constant
Time-criticalTHREAD_PRIORITY_TIME_CRITICAL
HighestTHREAD_PRIORITY_HIGHEST
Above normalTHREAD_PRIORITY_ABOVE_NORMAL
NormalTHREAD_PRIORITY_NORMAL
Below normalTHREAD_PRIORITY_BELOW_NORMAL
LowestTHREAD_PRIORITY_LOWEST
IdleTHREAD_PRIORITY_IDLE

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Linux系统中,可以使用`sched_setscheduler`函数来设置线程调度策略和优先级。该函数的原型如下: ```c #include <sched.h> int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param); ``` 其中,`pid`参数指定要设置的线程的进程ID,如果`pid`为0,则表示设置当前线程调度策略和优先级。`policy`参数指定调度策略,可以是以下三种之一: - `SCHED_FIFO`:先进先出调度策略。 - `SCHED_RR`:时间片轮转调度策略。 - `SCHED_OTHER`:普通调度策略。 `param`参数是一个指向`sched_param`结构体的指针,用于指定线程优先级。该结构体定义如下: ```c struct sched_param { int sched_priority; // 线程优先级 }; ``` `sched_priority`成员指定线程优先级,取值范围为0~99,数值越大表示优先级越高。 下面是一个示例代码,演示如何使用`sched_setscheduler`函数设置线程调度策略和优先级: ```c #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <sched.h> void *thread_func(void *arg) { int i; for (i = 0; i < 5; i++) { printf("Thread %ld is running\n", (long)arg); sleep(1); } return NULL; } int main() { pthread_t tid1, tid2; struct sched_param param; int policy, ret; // 创建两个线程 ret = pthread_create(&tid1, NULL, thread_func, (void *)1); if (ret != 0) { perror("pthread_create"); exit(EXIT_FAILURE); } ret = pthread_create(&tid2, NULL, thread_func, (void *)2); if (ret != 0) { perror("pthread_create"); exit(EXIT_FAILURE); } // 获取当前线程调度策略和优先级 policy = sched_getscheduler(0); printf("Current thread's scheduling policy is %d\n", policy); ret = sched_getparam(0, &param); if (ret != 0) { perror("sched_getparam"); exit(EXIT_FAILURE); } printf("Current thread's priority is %d\n", param.sched_priority); // 设置线程调度策略和优先级 param.sched_priority = 80; ret = sched_setscheduler(0, SCHED_FIFO, &param); if (ret != 0) { perror("sched_setscheduler"); exit(EXIT_FAILURE); } // 获取设置后的线程调度策略和优先级 policy = sched_getscheduler(0); printf("Current thread's scheduling policy is %d\n", policy); ret = sched_getparam(0, &param); if (ret != 0) { perror("sched_getparam"); exit(EXIT_FAILURE); } printf("Current thread's priority is %d\n", param.sched_priority); // 等待线程结束 pthread_join(tid1, NULL); pthread_join(tid2, NULL); return 0; } ``` 该示例代码创建了两个线程,并使用`sched_setscheduler`函数将当前线程调度策略设置为先进先出调度策略,优先级设置为80。最后,等待两个线程结束。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值