在Linux下改變進(jìn)程的優(yōu)先級(jí)
作者:曾宏安,華清遠(yuǎn)見嵌入式學(xué)院講師。
作為多任務(wù)的操作系統(tǒng),Linux內(nèi)核為每個(gè)創(chuàng)建的進(jìn)程分配時(shí)間片并根據(jù)其優(yōu)先級(jí)進(jìn)行調(diào)度。當(dāng)進(jìn)程被創(chuàng)建時(shí),其對(duì)應(yīng)的task_struct里包含了四個(gè)優(yōu)先級(jí):
struct task_struct {
……
int prio, static_prio, normal_prio;
unsigned int rt_priority;
……
};
在內(nèi)核頭文件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)
內(nèi)核中規(guī)定進(jìn)程的優(yōu)先級(jí)范圍為[0, MAX_PRIO-1]。其中實(shí)時(shí)任務(wù)的優(yōu)先級(jí)范圍是[0, MAX_RT_PRIO-1],非實(shí)時(shí)任務(wù)的優(yōu)先級(jí)范圍是[MAX_RT_PRIO, MAX_PRIO-1]。優(yōu)先級(jí)值越小,意味著級(jí)別越高,任務(wù)先被內(nèi)核調(diào)度。
那任務(wù)的優(yōu)先級(jí)又是如何確定的呢?和task_struct中的成員是什么關(guān)系?
① prio指的是任務(wù)當(dāng)前的動(dòng)態(tài)優(yōu)先級(jí),其值影響任務(wù)的調(diào)度順序。
② normal_prio指的是任務(wù)的常規(guī)優(yōu)先級(jí),該值基于static_prio和調(diào)度策略計(jì)算。
③ static_prio指的是任務(wù)的靜態(tài)優(yōu)先級(jí),在進(jìn)程創(chuàng)建時(shí)分配,該值會(huì)影響分配給任務(wù)的時(shí)間片的長(zhǎng)短和非實(shí)時(shí)任務(wù)動(dòng)態(tài)優(yōu)先級(jí)的計(jì)算。
④ rt_priority指的是任務(wù)的實(shí)時(shí)優(yōu)先級(jí)。若為0表示是非實(shí)時(shí)任務(wù),[1, 99]表示實(shí)時(shí)任務(wù),值越大,優(yōu)先級(jí)越高。
static_prio = MAX_RT_PRIO + 20 + nice(nice的缺省值是0,范圍[20, 19])
rt_priority缺省值為0,表示非實(shí)時(shí)任務(wù)。[1,99]表示實(shí)時(shí)任務(wù)
對(duì)于實(shí)時(shí)任務(wù),prio = normal_prio = static_prio
對(duì)于非實(shí)時(shí)任務(wù) prio = normal_prio = MAX_RT_PRIO – 1 – rt_priority
prio的值在使用實(shí)時(shí)互斥量時(shí)會(huì)暫時(shí)提升,釋放后恢復(fù)成normal_prio
下面來了解一下如何在應(yīng)用程序中改變進(jìn)程的優(yōu)先級(jí)。
#include <sys/time.h>
#include <sys/resource.h>
int setpriority(int which, int who, int prio);
//該函數(shù)可以修改進(jìn)程、進(jìn)程組或用戶所有進(jìn)程的nice值從而影響static_prio
which : PRIO_PROCESS // 修改某個(gè)進(jìn)程
PRIO_PGRP // 修改進(jìn)程組
PRIO_USER // 修改用戶所有進(jìn)程
who : 進(jìn)程號(hào)(0表示當(dāng)前調(diào)用進(jìn)程)、進(jìn)程組號(hào)或UID
prio : 新的用戶態(tài)優(yōu)先級(jí)(即nice值,范圍[-20,19])
返回值 : 執(zhí)行成功返回0,失敗返回-1并設(shè)置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;
};
// 該函數(shù)修改某個(gè)進(jìn)程的調(diào)度策略和rt_priority
pid : 要修改的進(jìn)程號(hào),0表示當(dāng)前調(diào)用進(jìn)程
policy : 調(diào)度策略
SCHED_OTHER(針對(duì)非實(shí)時(shí)進(jìn)程的調(diào)度策略)
SCHED_RR(針對(duì)實(shí)時(shí)進(jìn)程的輪轉(zhuǎn)調(diào)度策略)
SCHED_FIFO(針對(duì)實(shí)時(shí)進(jìn)程的先進(jìn)先出調(diào)度策略)
param : 指向的結(jié)構(gòu)體中存放著要設(shè)置的rt_priority
返回值 : 執(zhí)行成功返回0,失敗返回-1并設(shè)置errno
……
struct sched_param sp = {1};
if (sched_setscheduler(0, SCHED_FIFO, &sp) < 0)
{
perror(“fail to sched_setscheduler”);
exit(-1);
}
……




