《linux内核完全剖析》笔记04-任务调度
来源:互联网 发布:光翼网络班多少钱 编辑:程序博客网 时间:2024/06/05 14:46
问题:
- 任务调度在何时发生
- 任务调度的基本策略是什么
- 任务切换时怎么做到的
1. 隐含的睡眠队列
建立睡眠等待队列的原因,是因为有先后顺序等待某项资源,然后要按顺序唤醒进程,就要依照这里隐含的队列顺序进行
sched.c第171行
static inline void __sleep_on(struct task_struct **p, int state){ struct task_struct *tmp; if (!p) return; if (current == &(init_task.task)) panic("task[0] trying to sleep"); tmp = *p; *p = current; current->state = state;repeat: schedule(); //这里的*p的内容,有可能不是上面的*p的内容即不是当前任务,也有可能是 //不是当前任务是因为在其它进程执行本函数时__sleep_on设置的 if (*p && *p != current) { (**p).state = 0; current->state = TASK_UNINTERRUPTIBLE; goto repeat; } if (!*p) printk("Warning: *P = NULL\n\r"); if (*p = tmp) tmp->state=0;}
以下这张图展示了这个队列的大概样子,上面方块代表__sleep_on函数块,需要了解这个机制,是因为很多其它的子系统也用到类似的方法,这也是了解睡眠机制的关键
2. 任务调度在何时发生
任务状态发生改变的时候都会要重新调度,比如睡眠了一个进程(任务),自然就要重新选一个进程继续运行,在者要是没有任务发生改变时,时间中断回调函数,会在每10ms到来时运行一次
sched.c第324行
void do_timer(long cpl){ ... //current->counter > 0意思是当前任务还有分配给他的时间片 if ((--current->counter)>0) return; current->counter=0; if (!cpl) return; //重点:重新调度 schedule();}
3. 任务调度的基本策略
sched.c第120行
void schedule(void){ .../* this is the scheduler proper: */ while (1) { c = -1; next = 0; i = NR_TASKS; p = &task[NR_TASKS]; //挑选一个就绪态运行的进程且时间片最大的那个进程 while (--i) { if (!*--p) continue; if ((*p)->state == TASK_RUNNING && (*p)->counter > c) c = (*p)->counter, next = i; } //没有找到怎么办?你猜猜 if (c) break; for(p = &LAST_TASK ; p > &FIRST_TASK ; --p) if (*p) (*p)->counter = ((*p)->counter >> 1) + (*p)->priority; } //切换进程 switch_to(next);}
备注:
- 选取超时时间最少也就是分配的时间片最多的那个进程进行切换
- 调度性能与进程的数目成线性关系,进程越多性能越差
4. 切换任务的代码分析
先来看看TSS段描述符的格式:
然后再来看看_TSS宏,它是寻找GDT表中本进程的tss描述符的选择符号值,每个任务包含一个ldt选择符和tss选择符
//每个任务有一个8字节的tss选择符和8字节的ldt选择子一共16字节//任务为n偏移2^4字节#define _TSS(n) ((((unsigned long) n)<<4)+(FIRST_TSS_ENTRY<<3))
切换代码分析
#define switch_to(n) {\struct {long a,b;} __tmp; \/*是不是当前任务,是就不用切换直接跳到下面标号为的地方*/__asm__("cmpl %%ecx,_current\n\t" \ "je 1f\n\t" \ /* %dx装载下面的_TSS(n),也就是tss段描述符的值 放到%1,%1代表__tmp.b处 */ "movw %%dx,%1\n\t" \ /*%ecx为保存为切换出来的任务*/ "xchgl %%ecx,_current\n\t" \ /*长跳到__tmp.a处的任务,也就是上面tss保存到__tmp.b的进程*/ "ljmp %0\n\t" \ "cmpl %%ecx,_last_task_used_math\n\t" \ "jne 1f\n\t" \ "clts\n" \ "1:" \ ::"m" (*&__tmp.a),"m" (*&__tmp.b), \ "d" (_TSS(n)),"c" ((long) task[n])); \}
结束语:
0.12版本的进程调度策略比较简单,但给了我们理解进程调度的核心意思,最新的linux代码仍然使用switch_to宏,只是已经做了非常的优化工作
0 0
- 《linux内核完全剖析》笔记04-任务调度
- 《linux内核完全剖析》笔记05-任务退出
- 《Linux内核完全剖析》阅读笔记
- 《Linux内核完全剖析》阅读笔记
- 《Linux内核完全剖析》阅读笔记
- 《Linux内核完全剖析》阅读笔记
- linux内核完全剖析0.12笔记--第一章,概述
- 《linux 内核完全剖析》 笔记 CODE_SPACE 宏定义分析
- 《linux 内核完全剖析》 signal.c 代码分析笔记
- 《linux 内核完全剖析》 exit.c 代码分析笔记
- 《linux 内核完全剖析》 fork.c 代码分析笔记
- 《linux 内核完全剖析》 vsprintf.c 代码笔记
- linux内核完全剖析 学习笔记 打字太累 截图
- 《linux内核完全剖析》笔记01-启动分析
- 《linux内核完全剖析》笔记02-中断处理
- 《linux内核完全剖析》笔记03-进程创建
- 《linux内核完全剖析》笔记06-内存管理
- 《Linux内核完全剖析》读书笔记
- FreeRTOS移植笔记(一)创建工程模板
- JavaScript
- eclipse如何修改dynamic web module version
- 安卓成长记(二)
- Spring 注入问题
- 《linux内核完全剖析》笔记04-任务调度
- python读取xml文件
- matlab画动画
- 第三章 加分的
- Jquery读取json文件和xml文件以及解析
- Python下CGIweb服务器实现(CGIHTTPServer) 《Head First Python》第七章
- ActionBar的Home按钮实现
- Hadoop+HBase完全分布式安装
- 编程思想笔记 01