linux runqueue定义,Linux中多CPU的runqueue及抢占

一、引出

在在嵌入式操作系统中,很多线程都可以为实时任务,因为毕竟这些线程很少和人接触,而是面向任务的。所有就有一个抢占的时机问题。特别是2.6内核中引入了新的内核态抢占任务,所以就可以说一下这个内核态抢占的实现。

内核态抢占主要发生在两个时机,一个是主动的检测是否需要抢占,另一个就是在异常处理完之后的异常判断。

#define preempt_enable() \

do { \

preempt_enable_no_resched(); \

barrier(); \

preempt_check_resched(); \

} while (0)

这一点和用户态的pthread_setcanceltype中也有使用,也就是如果禁止线程的异步取消,在使能之后的第一时间判断线程是不是已经被取消,包括内核态对信号的处理也是如此,例如,当sigprocmask开启一个信号屏蔽之后,也需要在第一时间来判断系统中是否有未处理的信号,如果有则需要及时处理,这个操作是在sys_sigprocmask--->>>recalc_sigpending--->>>set_tsk_thread_flag(t, TIF_SIGPENDING)中完成。

另一个就是内核线程无法预测的中断或者异常处理结束之后的判断。

linux-2.6.21\arch\i386\kernel\entry.S:  ret_from_exception(ret_from_intr)--->>>>

#ifdef CONFIG_PREEMPT

ENTRY(resume_kernel)

DISABLE_INTERRUPTS(CLBR_ANY)

cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ?首先判断线程是否禁止了抢占,如果禁止抢占,则不检测是否重新调度标志。

jnz restore_nocheck

need_resched:

movl TI_flags(%ebp), %ecx # need_resched set ?

testb $_TIF_NEED_RESCHED, %cl检测是否需要重新调度。

jz restore_all

testl $IF_MASK,PT_EFLAGS(%esp) # interrupts off (exception path) ?

jz restore_all

call preempt_schedule_irq 这里就是第二个抢占发生的时机,就是内核线程不可预测的时候发生的。

jmp need_resched

END(resume_kernel)

在preempt_schedule_irq中引入了一个比较常见的概念,就是这个PREEMPT_ACTIVE,

add_preempt_count(PREEMPT_ACTIVE);

/*

* We use bit 30 of the preempt_count toindicate that kernel

* preemption is occurring.  See include/asm-arm/hardirq.h.

*/

#define PREEMPT_ACTIVE 0x40000000

这个标志位在内核中的线程抢占统计中将会用到,在schedule函数中

switch_count = &prev->nivcsw;

if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {这里判断的是抢占标志是否被置位,如果没有置位,也就是如果不是被抢占,则认为是自愿放弃CPU,也就是Voluntary释放CPU,否则认为是被抢占。

switch_count = &prev->nvcsw;

if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&

unlikely(signal_pending(prev))))

prev->state = TASK_RUNNING;

else {

if (prev->state == TASK_UNINTERRUPTIBLE)

rq->nr_uninterruptible++;

deactivate_task(prev, rq);

}

}

通过/proc/$PID/status可以看到这个切换次数记录。

static inline void task_context_switch_counts(struct seq_file *m,

struct task_struct *p)

{

seq_printf(m, "voluntary_ctxt_switches:\t%lu\n"

"nonvoluntary_ctxt_switches:\t%lu\n",

p->nvcsw,

p->nivcsw);

}

从调度的代码中可以看到,如果线程禁止了抢占,那么线程是不能执行调度的,这样可以推出线程在关掉抢占之后不能睡眠,如果需要等待,应该应该用spinlock,在asmlinkage void __sched schedule(void)的开始有这个判断

if (unlikely(in_atomic() && !current->exit_state)) {

printk(KERN_ERR "BUG: scheduling while atomic: "

"%s/0x%08x/%d\n",

current->comm, preempt_count(), current->pid);

debug_show_held_locks(current);

if (irqs_disabled())

print_irqtrace_events(current);

dump_stack();

}

也就是,如果 线程是禁止抢占之后进行调度,后果是很严重的,直接内核就dump_stack了(但是没有panic,至少对386是如此)。这一点也容易理解,因为在自愿和非自愿的两个抢占判断中,都判断了线程的preempt_count的值,如果非零就退出,所以应该是不能走到这一步的。

二、多核中的运行队列

这个在大型服务器中是比较有用的一个概念,就是线程在CPU之间的均匀分配或者非均匀分配问题。目的就是让各个CPU尽量负载平衡,不要忙的忙死,闲的闲死。按照计算机的原始概念,CPU可以作为一个资源,然后等待使用这个资源的线程就需要排队。如果要排队,就需要有一个约定的地点让大家在这里排队,这样便于管理,比如说先来先服务,然后优先级的判断等。

在内核里,这个队列就是每个CPU都定义的一个为struct rq 结构的runqueue变量,这个是每个CPU的一个排队区,可以认为是CPU的一个私有资源,并且是静态分配,每个CPU有天生拥有这么一个队列,拿人权的角度看,这个也就是CPU的一个基本权利,并且是一个内置权利。当CPU存在之后,它的runqueue就存在了。注意:这是一个容器,它是用来存放它的客户线程的,所以的线程在这里进行汇集和等待;对每个CPU来说,它的这个结构本身是不会变化的,变化的只是这个队列中的线程,一个线程可以在这个CPU队列里等待并运行,也可以在另一个CPU中运行,当然不能同时运行。这个变量的定义为

static DEFINE_PER_CPU(struct rq, runqueues);

现在,一个CPU需要服务的所有的线程都在这个结构里,所以也就包含了实时线程组和非实时线程组,它们在rq的体现为两个成员。

struct cfs_rq cfs;

struct rt_rq rt;

同一个CPU上的两个运行队列采用不同的调度策略,实时策略也就是内核中希望实现的O(1)调度器,所以它的内容中包含了100个实时队列结构。这个结构也和信号相同,首先有一个位图,表示这个优先级是否有可运行线程,然后有一个指针数组,指向各个优先级的就绪线程,前者用于快速判断最高优先级队列下表,后者用于真正取出该优先级的线程。

对于cfs调度,它一般是为了保证系统中线程对用户的及时响应,也就是说这个线程和用户交互,不能让用户感觉到某个任务有“卡”的感觉。保证这个流畅的方法就是快速切换,从而在某个时间段内所有的cfs任务都可以被运行一次。也就是不会出现某个任务跑的很欢乐,另外某个跑的很苦逼。

这个的实现就是大家经常说的内核红黑树结构,很多地方都有说明。这里注意红黑树是一个有序树,有序就需要有键值,并且有键值的比较方法。在内核中这个键值就是每个线程的一个调度实体的vruntime成员,在linux-2.6.37.1\kernel\sched_fair.c中我们看到的键值比较为put_prev_task_fair--->>>put_prev_entity--->>>__enqueue_entity--->>>entity_key

static inline s64 entity_key(struct cfs_rq *cfs_rq, struct sched_entity *se)

{

return se->vruntime - cfs_rq->min_vruntime;

}

而这个调度实体是一个抽象的概念,它可能考虑到了任务组的调度吧。实时任务和cfs任务的调度实体结构并不相同,并且这个两个在task_struct结构中两个并不是一个union,而是实实在在两个独立的实体,在task_struct结构中可以看到:

struct sched_entity se;

struct sched_rt_entity rt;

这个可能是为了保证线程的优先级可以在运行时通过sys_sched_setscheduler来动态修改而设置的吧。

对于一个runqueue,它对应一个CPU,由于一个CPU上只能同时运行一个线程,所以一个runqueue只有一个curr,因为我们可以看到一个rq有一个curr结构

struct task_struct *curr, *idle, *stop;

注意的是,同一时间真正使用CPU的线程只有一个,但是一个CPU上可以有多个线程都是处于就绪状态,也就是running状态,我们可以看到这个running在rq、rt_rq、cfs_rq中都有相应的成员(nr_running)。这里说的running并不是他们在运行,而是可运行,他们是用来进行CPU之间负载均衡的,和是否正在CPU上运行没有直接关系。反过来,一个线程是否处于可运行状态,是通过p->se.on_rq 来判断的。

我们看一下系统唤醒一个线程时的操作:

wake_up_new_task--->>>activate_task--->>enqueue_task

p->se.on_rq = 1; 这里可以看到,实时任务也是用了task_struct中的struct sched_entity se;成员,所以可以认为这是一个线程固有的成员,而struct sched_rt_entity rt;是为rt线程专门另外设置的一个附加成员,它们不是互斥或者说可替代的,而是基础和附加属性的关系。

而对于某个CPU上正在运行的线程的判断则使用的是

static inline int task_current(struct rq *rq, struct task_struct *p)

{

return rq->curr == p;

}

而对于nr_running的设置为

wake_up_new_task--->>>activate_task--->>inc_nr_running(rq);

static void inc_nr_running(struct rq *rq)

{

rq->nr_running++;

}

标签:task,抢占,rq,runqueue,线程,中多,CPU,struct

来源: https://www.cnblogs.com/tsecer/p/10485824.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/563146.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c语言中把时间拷到字符串中,C语言中将日期和时间以字符串格式输出的方法

ctime()函数:头文件:#include 定义函数:char *ctime(const time_t *timep);函数说明:ctime()将参数timep 所指的time_t 结构中的信息转换成真实世界所使用的时间日期表示方法,然后将结果以字符串形态返回。此函数已经由…

c语言补全程序,跪求高手解答简单的程序补全题~!

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼英勇的你不断疯狂的射击天上的幽灵,这些太空怪物也毫不留情地还击,逼得你只好左闪右闪地躲,但是你仍奋战不懈,穿梭于枪林弹雨之中,直到你消灭所有的幽灵,或者是…

数控机床需要c语言程序吗,数控机床编程与操作--详细介绍

前言第1章 数控机床加工概述111 数控加工概述1111 数控技术1112 数控加工的概念212 数控机床的组成和分类2121 数控机床的组成2122 数控机床的工作原理5123 数控机床的分类513 数控机床的特点和应用范围10131 数控机床加工的…

c语言数学语文英语成绩编程,急求一编程题!…

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼#include #include "stdlib.h"int i,j;struct STUDENT{int xuehao;float yuwen;float shuxue;float yingyu;float sum;float average;}student[3];void huhuan1(int a,int b){int c; ca;ab;bc;}void huhuan(float x,floa…

c语言英文星期几,输入字母,判断星期几,求大神指点

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼#includevoid uh() //判断周二还是周三{ char sec;printf("请继续输入:\n");bq:scanf("%c",&sec);if(secu||secU)printf("It is Tuesday!\n");else if(secH||sech)printf("It i…

c语言怎么判断文件类型,判断你的文件是否为合法的PE文件和应用类型

作者:赖锋源代码下载可能很多的人都没有注意到一些事情,就是你的程序是不是合法的可运行的应用程序,例如一个文件只是把后缀改成 .exe 的形式就显示为应用程序的图标了! 你不想写一个根据后缀名就确定应用程序类型的程序吧!这样太哪个了吧!解…

c语言项开发班级登入系统,c语言--班级管理系统

满意答案dgfetc5832013.12.10采纳率:47% 等级:12已帮助:14710人class student{public:char m_strName[10]; // 姓名int m_nNum; // 学号float m_dScore[4]; // 成绩};void InputScore(student* p, int nNumber){if(nNumber > 10){print…

android 高度百分比,如何在Android中进行百分比高度和宽度?

现在,可以用Guidelines定位百分比值xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.com/apk/res-auto"android:layout_width"match_parent"android:layout_height"match_parent&q…

android 知识点大全,Android基础知识总结(一)

1.面向对象(OOP):针对业务处理过程的实体及其属性和行为进行抽象封装以获得高效清晰的逻辑单元划分。三大特性:①封装(隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变量隔离便于使用,提高代码的服用小和安全性…

android fragment 弹出对话框,Android中使用Dialogfragment显示对话框

其他注意事项:1、如何设置自己的Dialogfragment没有标题栏?可以通过两种方法来设置 ,一种是使用dialogfragment的setStyle函数,另外就是使用getDialog().getWindow().requestFeature方法,具体代码如下Overridepublic D…

android sd卡不可写,Android检查SD卡是否可读写

因为external storage可能是不可用的,比如遇到SD卡被拔出等情况时。因此在访问之前应对其可用性进行检查。我们可以通过执 行 getExternalStorageState()来查询external storage的状态。若返回状态为MEDIA_MOUNTED, 则 可以读写。/* Checks if external storage is …

Android7.0 emui主题,全新EMUI5.0基于Android7.0 天生快,一生快!

EMUI5.0是基于Android 7.0开发的全新一代操作系统。 循着神秘古老的爱琴海带来的灵感,EMUI5.0用户界面的设计极其简单干净,令人赏心悦目。 因了解用户习惯而全新改善,EMUI5.0流畅自然的表现不会随时间递减,让生活得心应手&#xf…

html生成原理,Axure生成HTML的原理是什么?

回答:云渲染平台分布式并行计算分为空间上的并行和时间上的并行。空间上的并行是指用多个处理器并发的执行计算,比如Mentalray渲染器就支持单帧画面分割渲染,时间上的并行就是指流水线技术。云渲染平台现在的集群计算系统的前沿科学研究主要是…

在微信公众号中写html代码吗,微信公众号代码编写怎么做

微信公众号编写微信代码,因为有这方面的需要,需要去进行微信公众号代码编写。以下是学习啦小编为您带来的关于微信公众号代码编写,希望对您有所帮助。微信公众号代码编写微信公众平台编辑器不能直接编写微信代码,但是可以通过第三…

html代码在线分析,网站html代码解析

1、什么是HTML文件?HTML中文叫做“超文本标记语言”,一个HTML文件不仅包含文本内容,还包含一些标记,一个HTML文件的后缀名是.htm或者是.html。用文本编辑器(Dreamweaver)就可以编写HTML文件。2、html文件的基本结构:(成…

html 下拉到一定位置,浏览器向下滚动到一定位置继续滚动时,侧边导航固定在页面顶部,再滚动到一定位置时页面再向下滚动侧边导航不再固定。这种效果怎么实现呢...

1.浏览器向下滚动到一定位置继续滚动时,侧边导航固定在页面顶部,再滚动到一定位置时页面再向下滚动侧边导航不再固定。页面向上滚动到一定位置继续滚动时,侧边导航保持在原来位置。这种效果怎么实现呢2.、参考代码:$(function(){/…

济源一中2021高考成绩查询入口,济源一中2019高考成绩喜报、一本二本上线人数情况...

济源一中2019年高考喜报2019年高考成绩揭晓,济源一中再创辉煌!普通类(不含体育、艺术)一本上线突破1500大关,达到1549人,比去年增加51人,再创历史新高。高分段成绩喜人,全省文科裸分前50名,我校…

用户可以改变计算机功能键吗,电脑键盘快捷键怎么更改

许多用户朋友想更改自己电脑的快捷键?下面小编整理了解决更改电脑快捷键的方法,希望能帮到大家O***∩_∩***O哈哈~更改电脑快捷键的方法点击电脑屏幕的最左下角的“开始菜单”,此时弹出总程序菜单,如图:点击【所有程序】&#xf…

2017年网络统考计算机成绩,2017年12月江苏省成人计算机基础统考成绩查询

问: 关于江苏省成人高考计算机统考答:成人教育的学生在校期间每年6月/1月有二次省计算机统考,考试大纲你可以在江苏省教育考试院网上查询。考试内容全在里面,像你说的有WORD 、EXCEL PPT 、(没有CAD)。一般学校会开设此课程。每一个学生必须通…

计算机专业的英语文献,计算机专业英语论文参考文献

bentuoguai高分答主08-08TA获得超过1351个赞关于计算机信息管理系统,可以参考了:)~~Enterprise computer network management information system(MIS) is gradually use, it is the stage sign of our country of production power development, is the…