作爲多任務的操作系統,Linux內核爲每個創建的進程分配時間片並根據其優先級進行調度。當進程被創建時,其對應的task_struct裏包含了四個優先級:
struct task_struct {
……
int prio, static_prio, normal_prio;
unsigned int rt_priority;
……
};
在內核頭文件include/linux/sched.h中定義瞭如下宏
#define MAX_USER_RT_PRIO 100
#define MAX_RT_PRIO MAX_USER_RT_PRIO
#define MAX_PRIO (MAX_RT_PRIO + 40)
內核中規定進程的優先級範圍爲[0, MAX_PRIO-1]。其中實時任務的優先級範圍是[0, MAX_RT_PRIO-1],非實時任務的優先級範圍是[MAX_RT_PRIO, MAX_PRIO-1]。優先級值越小,意味着級別越高,任務先被內核調度。
那任務的優先級又是如何確定的呢?和task_struct中的成員是什麼關係?
① prio指的是任務當前的動態優先級,其值影響任務的調度順序。
② normal_prio指的是任務的常規優先級,該值基於static_prio和調度策略計算。
③ static_prio指的是任務的靜態優先級,在進程創建時分配,該值會影響分配給任務的時間片的長短和非實時任務動態優先級的計算。
④ rt_priority指的是任務的實時優先級。若爲0表示是非實時任務,[1, 99]表示實時任務,值越大,優先級越高。
static_prio = MAX_RT_PRIO + 20 + nice(nice的缺省值是0,範圍[20, 19])
rt_priority缺省值爲0,表示非實時任務。[1,99]表示實時任務
對於實時任務,prio = normal_prio = static_prio
對於非實時任務 prio = normal_prio = MAX_RT_PRIO – 1 – rt_priority
prio的值在使用實時互斥量時會暫時提升,釋放後恢復成normal_prio
下面來了解一下如何在應用程序中改變進程的優先級。
#include <sys/time.h>
#include <sys/resource.h>
int setpriority(int which, int who, int prio);
//該函數可以修改進程、進程組或用戶所有進程的nice值從而影響static_prio
which : PRIO_PROCESS // 修改某個進程
PRIO_PGRP // 修改進程組
PRIO_USER // 修改用戶所有進程
who : 進程號(0表示當前調用進程)、進程組號或UID
prio : 新的用戶態優先級(即nice值,範圍[-20,19])
返回值 : 執行成功返回0,失敗返回-1並設置errno
……
if (setpriority(PRO_PROCESS, 0, 2) <0)
{
perror(“fail to setpriority”);
exit(-1);
}
……
************************************************************************
#include <sched.h>
int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param);
struct sched_param
{
int __sched_priority;
};
// 該函數修改某個進程的調度策略和rt_priority
pid : 要修改的進程號,0表示當前調用進程
policy : 調度策略
SCHED_OTHER(針對非實時進程的調度策略)
SCHED_RR(針對實時進程的輪轉調度策略)
SCHED_FIFO(針對實時進程的先進先出調度策略)
param : 指向的結構體中存放着要設置的rt_priority
返回值 : 執行成功返回0,失敗返回-1並設置errno
……
struct sched_param sp = {1};
if (sched_setscheduler(0, SCHED_FIFO, &sp) < 0)
{
perror(“fail to sched_setscheduler”);
exit(-1);
}
……