导航:首页 > 操作系统 > linux设置线程优先级

linux设置线程优先级

发布时间:2023-05-27 05:34:02

‘壹’ linux系统进程调度

主要参考 :Linux manual page - sched

自从linux内核2.6.23以来,默认的进高哗扮程调度器就被设置为完全公平调度器(CFS,complete fair scheler),取代了之前的O(1)调度器。

每个线程都有一个静态调度优先级,即 sched_priority 字段。

一个线程的调度策略决定了线程会被插入到同级静态优先级的线程队列的位置,以及它在队列中会怎样移动。

所有的调度都是可插入的,如果一个更高静态优先级的线程准备好了,现在运行中的线程就会被插入。而调度策略则仅仅影响了同样静态优先级的线程。

进程(线程)可以通过系芦桥统调用设置自身或者其他进程(线程)的调度策略。

其中 pid 为0时,设置自身的调度策略和参数。结构体 sched_attr 包含以下戚灶字段: size 、 sched_policy (即调度策略,具体会在下一节介绍)、 sched_flags 、 sched_nice 、 sched_runtime 、 sched_deadline 、 sched_period (最后三个为 SCHED_DEADLINE 相关的参数)。当设置成功,系统调用返回0;否则返回-1,并会设置 errno 。

普通进程: SCHED_OTHER / SCHED_BATCH / SCHED_IDLE
实时进程: SCHED_FIFO / SCHED_RR
特殊实时进程: SCHED_DEADLINE
静态优先级:Static_priority:对于普通进程,静态优先级为0;对于实时进程,静态优先级为1-99,99为最高优先级。
动态优先级:Dynamic_priority:仅对普通进程有用,取决于nice和一个动态调整的量(比如进程ready却没被调度,则增加)。

‘贰’ linux c如何调整线程优先级

你好。

在分时系隐数统里应该没什必要吧

setpriority/getpriority,这两个函数描述的是改变进程优先级。

但是在linux中线程就是一个轻量级的山辩进程,

所以这两个函数是可以作用于单独的线程的

如果我的回答没能帮助您,请继续逗携缺追问。

‘叁’ linux查看线程优先级命令

用top或者ps -l查看进程会发现有PR(PRI) NI两个字段:

NI 是优先值,是用户层面的概念, PR是进程的实际优先级, 是给内核(kernel)看(用)的。
一般情况下,PR=NI+20, 如果一个进程的优先级PR是20, 那么它的NI(nice)值就是20-20=0。
进程调度优先级是从-20到19,一共40个级别,数字越大,表示进程的优先级越低。默认时候,进程的优先级是0。查看进程优先级有两个办法:ps和top。top命令显示的NI列的值。或者可以使用ps -efl来查看,也是在ni列表示了进程的优先级。《Linux就该这么学》 一起学习,进程的优先级可以在程序运行的时候设置,也可以在程序运行过程中动态的修改。

‘肆’ 在Linux下怎么修改当前线程的优先级

pthread_create()中的attr参数的__schedpolicy成员,表示新线程的调度策略,主要包括SCHED_OTHER(正常、非实时)、SCHED_RR(实时、轮转法)和SCHED_FIFO(实时、先入先出)三种,缺省为SCHED_OTHER,后两种调度策略仅对超级用户有效。运行时可以用过pthread_setschedparam()来改变。
__schedparam成员是一个struct sched_param结构,目前仅有一个sched_priority整型变量表示线程的运行优先级。这个参数仅当调度策略为实时(即SCHED_RR或SCHED_FIFO)时才有效,并可以在运行时通过pthread_setschedparam()函数来改变,缺省为0

‘伍’ linux进程、线程及调度算法(三)

调度策略值得是大家都在ready时,并且CPU已经被调度时,决定谁来运行,谁来被调度。

两者之间有一定矛盾。
响应的优化,意味着高优先级会抢占优先级,会花时间在上下文切换,会影响吞吐。
上下文切换的时间是很短的,几微妙就能搞定。上下文切换本身对吞吐并多大影响, 重要的是,切换后引起的cpu 的 cache miss.
每次切换APP, 数据都要重新load一次。
Linux 会尽可能的在响应与吞吐之间寻找平衡。比如在编译linux的时候,会让你选择 kernal features -> Preemption model.
抢占模型会影响linux的调度算法。

所以 ARM 的架构都是big+LITTLE, 一个很猛CPU+ 多个 性能较差的 CPU, 那么可以把I/O型任务的调度 放在 LITTLE CPU上。需要计算的放在big上。

早期2.6 内核将优先级划分了 0-139 bit的优先级。数值越低,优先级越高。0-99优先级 都是 RT(即时响应)的 ,100-139都是非RT的,即normal。
调度的时候 看哪个bitmap 中的 优先级上有任务ready。可能多个任务哦。

在普通优先级线程调度中,高优先级并不代表对低优先级的绝对优势。会在不同优先级进行轮转。
100 就是比101高,101也会比102高,但100 不会堵着101。
众屌丝进程在轮转时,优先级高的:

初始设置nice值为0,linux 会探测 你是喜欢睡眠,还是干活。越喜欢睡,linux 越奖励你,优先级上升(nice值减少)。越喜欢干活,优先级下降(nice值增加)。所以一个进程在linux中,干着干着 优先级越低,睡着睡着 优先级越高。

后期linux补丁中

红黑树,数据结构, 左边节点小于右边节点
同时兼顾了 CPU/IO 和 nice。
数值代表着 进程运行到目前为止的virtual runtime 时间。

(pyhsical runtime) / weight * 1024(系数)。
优先调度 节点值(vruntime)最小的线程。权重weight 其实有nice 来控制。

一个线程一旦被调度到,则物理运行时间增加,vruntime增加,往左边走。
weight的增加,也导致vruntime减小,往右边走。
总之 CFS让线程 从左滚到右,从右滚到左。即照顾了I/O(喜欢睡,分子小) 也 照顾了 nice值低(分母高).所以 由喜欢睡,nice值又低的线程,最容易被调度到。
自动调整,无需向nice一样做出奖励惩罚动作,个人理解权重其实相当于nice

但是 此时 来一个 0-99的线程,进行RT调度,都可以瞬间秒杀你!因为人家不是普通的,是RT的!

一个多线程的进程中,每个线程的调度的策略 如 fifo rr normal, 都可以不同。每一个的优先级都可以不一样。
实验举例, 创建2个线程,同时开2个:

运行2次,创建两个进程
sudo renice -n -5(nice -5级别) -g(global), 会明显看到 一个进程的CPU占用率是另一个的 3倍。

为什么cpu都已经达到200%,为什么系统不觉得卡呢?因为,我们的线程在未设置优先级时,是normal调度模式,且是 CPU消耗型 调度级别其实不高。

利用chrt工具,可以将进程 调整为 50 从normal的调度策略 升为RT (fifo)级别的调度策略,会出现:

chrt , nice renice 的调度策略 都是以线程为单位的,以上 设置的将进程下的所有线程进行设置nice值
线程是调度单位,进程不是,进程是资源封装单位!

两个同样死循环的normal优先级线程,其中一个nice值降低,该线程的CPU 利用率就会比另一个CPU的利用率高。

‘陆’ C++在linux下怎么多线程

#ifndefTHREAD_H_
#defineTHREAD_H_
#include<unistd.h>
#include<pthread.h>
classRunnable
{
public:
//运行实体
virtualvoidrun()=0;
};
//线程类
classThread:publicRunnable
{
private:
//线程初始化号
staticintthread_init_number;
//当前线程初始化序号
intcurrent_thread_init_number;
//线程体
Runnable*target;
//当前线程的线程ID
pthread_ttid;
//线程的状态
intthread_status;
//线程属性
pthread_attr_tattr;
//线程优先级
sched_paramparam;
//获取执行方法的指针
staticvoid*run0(void*pVoid);
//内部执行方法
void*run1();
//获取线程序号
staticintget_next_thread_num();
public:
//线程的状态-新建
staticconstintTHREAD_STATUS_NEW=0;
//线程的状态-正在运行
staticconstintTHREAD_STATUS_RUNNING=1;
//线程的状态-运行结束
staticconstintTHREAD_STATUS_EXIT=-1;
//构造函数
Thread();
//构造函数
Thread(Runnable*target);
//析构
~Thread();
//线程的运行体
voidrun();
//开始执行线程
boolstart();
//获取线程状态
intget_state();
//等待线程直至退出
voidjoin();
//等待线程退出或者超时
voidjoin(unsignedlongmillis_time);
//比较两个线程时候相同,通过current_thread_init_number判断
booloperator==(constThread*other_pthread);
//获取this线程ID
pthread_tget_thread_id();
//获取当前线程ID
staticpthread_tget_current_thread_id();
//当前线程是否和某个线程相等,通过tid判断
staticboolis_equals(Thread*iTarget);
//设置线程的类型:绑定/非绑定
voidset_thread_scope(boolisSystem);
//获取线程的类型:绑定/非绑定
boolget_thread_scope();
//设置线程的优先级,1-99,其中99为实时,意外的为普通
voidset_thread_priority(intpriority);
//获取线程的优先级
intget_thread_priority();
};
intThread::thread_init_number=1;
inlineintThread::get_next_thread_num()
{
returnthread_init_number++;
}
void*Thread::run0(void*pVoid)
{
Thread*p=(Thread*)pVoid;
p->run1();
returnp;
}
void*Thread::run1()
{
thread_status=THREAD_STATUS_RUNNING;
tid=pthread_self();
run();
thread_status=THREAD_STATUS_EXIT;
tid=0;
pthread_exit(NULL);
}
voidThread::run()
{
if(target!=NULL)
{
(*target).run();
}
}
Thread::Thread()
{
tid=0;
thread_status=THREAD_STATUS_NEW;
current_thread_init_number=get_next_thread_num();
pthread_attr_init(&attr);
}
Thread::Thread(Runnable*iTarget)
{
target=iTarget;
tid=0;
thread_status=THREAD_STATUS_NEW;
current_thread_init_number=get_next_thread_num();
pthread_attr_init(&attr);
}
Thread::~Thread()
{
pthread_attr_destroy(&attr);
}
boolThread::start()
{
returnpthread_create(&tid,&attr,run0,this);
}
inlinepthread_tThread::get_current_thread_id()
{
returnpthread_self();
}
inlinepthread_tThread::get_thread_id()
{
returntid;
}
inlineintThread::get_state()
{
returnthread_status;
}
voidThread::join()
{
if(tid>0)
{
pthread_join(tid,NULL);
}
}
voidThread::join(unsignedlongmillis_time)
{
if(tid==0)
{
return;
}
if(millis_time==0)
{
join();
}
else
{
unsignedlongk=0;
while(thread_status!=THREAD_STATUS_EXIT&&k<=millis_time)
{
usleep(100);
k++;
}
}
}
boolThread::operator==(constThread*other_pthread)
{
if(other_pthread==NULL)
{
returnfalse;
}if(current_thread_init_number==(*other_pthread).current_thread_init_number)
{
returntrue;
}
returnfalse;
}
boolThread::is_equals(Thread*iTarget)
{
if(iTarget==NULL)
{
returnfalse;
}
returnpthread_self()==iTarget->tid;
}
voidThread::set_thread_scope(boolisSystem)
{
if(isSystem)
{
pthread_attr_setscope(&attr,PTHREAD_SCOPE_SYSTEM);
}
else
{
pthread_attr_setscope(&attr,PTHREAD_SCOPE_PROCESS);
}
}
voidThread::set_thread_priority(intpriority)
{
pthread_attr_getschedparam(&attr,&param);
param.__sched_priority=priority;
pthread_attr_setschedparam(&attr,&param);
}
intThread::get_thread_priority(){
pthread_attr_getschedparam(&attr,&param);
returnparam.__sched_priority;
}
#endif/*THREAD_H_*/

‘柒’ 是指实时线程,Linux分配1-99为实时线程,是1为最高优先级还是99为最高

1是实时进程优先级最高的,99是实时进程优先级最低的,数字越小,优先级越高
你在做operating system的实验?

‘捌’ 嵌入式与Linux(五):Linux线程

姓名:王央京    学号:18050100052   学院:电子工程学院

转自:https://blog.csdn.net/qq_22847457/article/details/89371217

【嵌牛导读】本文介绍了Linux线程的相关信息

【嵌牛鼻子】Linux线程

【嵌牛提问】在了解Linux系统后,能否具体介绍线程的概念?

【嵌牛正文】

类Unix系统中,早期是没有“线程”概念的,80年代才引答握态入,借助进程机制实现出了线程的概念。因此在这类系统中,进程和线程关系密切。一个进程可以有多个线程,这个进程本身也叫做线程只不过是主线程。通常主线程分配任务给子线程做。程序设计时候就可以某一时刻不止做一件事情,每一个线程处理各自独立的任务。

多个线程可以访问相同的存储地址空间和文件描述符。同一进程内的线程共享以下数据:全局内存、进程指令、打开的文件、信号处理函数和信号处置、当前工作目录、用户ID和用户组ID、大多数数据。每个线程有各自的线程ID、寄存器集合(包括程序计数器和栈指针)、栈、errono、信号掩码、优先级。

线程的优点有提高程序并发性、开销小和数据通信、共享数据方便等。线程的缺点有库函数不稳定、调试编写困难、gdb不支持、对信号支持不好等。除此之外,多线程内如果其中一个线程出现了 除0、野指针 等问题会造成该线程崩溃,进而导致整个进程终止。同时,线程是进程的执行分支,线程出异常,就类似进程出异常,进而触发信号机制,终止进程,进程终止,该进程内的所有线程也就随即退出。

从上述分析来看,线程的优点相对突出,缺点均不是硬伤。Linux下由于实现方法导致进程、线程差别不是很大。

线程有一套完整的与其有关的函数库调用,它们中的绝大多数函数名都以pthread_开头。为了使用这些函数库调用,我们必须定义宏_REENTRANT,在程序中包含头文件pthread.h,并且在编译程序皮哗时需要用选项-lpthread来链接线程库。其中常用的函数库如下:

1.  pthread_self函数获取线程ID,其作用对应进程中getpid()函数。

2.  pthread_create函数创建一个新线程,其作用对应进程中fork()函数。

3.  pthread_exit函数将单个线程退出,其作用对应进程中exit()函数

4.  pthread_join函数阻塞等待线程退出,获取线程退出状态其作用,对清源应进程中waitpid()函数。

5.  pthread_cancel函数杀死(取消)线程其作用,对应进程中kill()函数。

6.  pthread_detach函数实现线程分离。

‘玖’ linux 信号灯中线程切换问题

(1)Posix标准中有有名信号灯和无名信号灯之分,对于有名信号灯,可以用sem_open来创建,其prototype是:

sem_t *sem_open(const char *name, int oflag);//打开已有的信号灯

sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned value);//一般是创建信号灯。

期中name是信号灯的名字, oflag是0, O_CREAT 或者 O_CREAT | O_EXCL, 如果指定O_CREAT, 那么mode和value对应创建该信号的模式和初始值。 如果指定了O_EXCL, 而且该信号灯已经在系统中存在,那调用会出错返回SEM_FAILED常量。 对于Linux内核来说,有名信号灯是很晚才加入内核中的,创建或是打开有名信号时候,应该指定”/semname“名字,对应的信号灯创建在/dev/shm目录下,名字是/dev/shm/sem.semname. BTW, 用gcc/g++编译实用信号灯功能的程序时候,应该引用librt库,(e.g., g++ -lrt sem.cpp). 关闭已打开的信号灯,用sem_close(sem_t *sem). 关闭信号灯并不意味着系统会删除它,要删除一个信号灯,需要调用sem_unlink(sem_t *sem)。 有名信号灯一般是为了进程之间同步实用的。 无名信号灯,一般是为一个进程内的不同线程之间同步使用的。 创建无名信号灯的方法如下:

sem_t sem;

sem_init(&sem, int shared, unsigned int value);//初始化信号灯。

......

sem_destroy(&sem);//清除信号灯。

(2)信号灯的使用和状态。

信号灯一般用来描述不同线程所共享的公共资源的数量,每一个信号灯都有一个叫做信号量的非负整数与之相连;信号量一般代表公共资源的数目,比如空闲列表中的缓冲区数目,视频中读入帧的数目,等等。对于一个线程可以用sem_wait, sem_post函数来改变一个信号灯的信号量。

sem_wait(sem_t &sem);

sem_wait的语义如下:

{

while(信号量==0)

等待; //此处线程被挂起,等待其他线程调用sem_post唤醒之。

信号量减1;

}

注意:测试信号量是否为零,和减一的操作是原子的,也就是说期间不会发生线程切换。

与sem_wait对应的调用是sem_post,语义如下:

{

信号量加1;

唤醒等待该信号量的线程;//调用sem_wait并等待的线程。

}

该操作也是原子的。

信号灯的状态可以用sem_getvalue来查看。一般来说sem_wait和sem_post的调用不必在同一个线程内成对出现(象mutex那样,lock/unlock要配对出现)。 一般的情形是这样的,一个线程等待资源可用,调用sem_wait, 另外一个线程生成资源,然后调用sem_post,唤醒等待该资源的线程。因为信号灯所描述的是线程间公共资源,使用的时候一般和mutex一起使用,mutex保证访问公共资源的线程排他性,信号灯表示资源的可用性。

‘拾’ 关于嵌入式系统线程调度与优先级的问题,wince或linux

你刚讲了线程1的优秀级高,那么中断来了之后,肯定要先处理这个线程。
系统不会强制结束当前的线程,如果这样做可能导致死机活崩溃,因为该线程可能是系统的。
正常的做法是将该线程的数据备份,处理优先级高的,之后再回来继续工作

阅读全文

与linux设置线程优先级相关的资料

热点内容
pdf魔鬼 浏览:29
二维数组递归解决算法问题 浏览:382
java反射例子 浏览:670
惠普笔记本自带解压软件 浏览:840
抖音视频后台压缩 浏览:707
app里的视频广告从哪里接的 浏览:556
天翼云服务器跟腾讯云 浏览:618
cyk算法实现 浏览:191
大潘号app在哪里可以下载 浏览:109
怎么做解压豌豆捏捏乐 浏览:618
安卓手机怎么调成苹果表情 浏览:755
android蓝牙声音 浏览:850
横盘震荡选股公式源码 浏览:589
子平pdf 浏览:507
hyper编程技巧 浏览:236
java带参数的线程 浏览:913
为什么安卓车载中控屏看起来很差 浏览:466
吃鸡怎么解压最快 浏览:968
linux网络编程基础 浏览:219
产研是程序员吗 浏览:594