linux内核学习-5任务调度(关注新浪微博:寂寞侵蚀的岁月(4000多篇技术分享))

void schedule(void)

105 {

106 int i,next,c;

107 struct task_struct ** p; // 任务结构指针的指针。

108

109 /* check alarm, wake up any interruptible tasks that have got a signal */

/* 检测alarm(进程的报警定时值),唤醒任何得到信号的可中断任务 */

110

// 从任务数组中最后一个任务开始检测alarm。

111 for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)

112 if (*p) {

// 如果任务的alarm 时间已经过期(alarm<jiffies),则在信号位图中置SIGALRM 信号,然后清alarm。

// jiffies 是系统从开机开始算起的滴答数(10ms/滴答)。定义在sched.h 第139 行。

113 if ((*p)->alarm && (*p)->alarm < jiffies) {

114 (*p)->signal |= (1<<(SIGALRM-1));

115 (*p)->alarm = 0;

116 }

// 如果信号位图中除去被阻塞的信号外还有其它信号并且任务处于可中断状态,则置任务为就绪状态。

// 其中‘~(_BLOCKABLE & (*p)->blocked)‘用于忽略被阻塞的信号,但SIGKILL 和SIGSTOP 不能被阻塞。

117 if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&

118 (*p)->state==TASK_INTERRUPTIBLE)

119 (*p)->state=TASK_RUNNING; //置为就绪(可执行)状态。

120 }

121

122 /* this is the scheduler proper: */

/* 这里是调度程序的主要部分 */

123

124 while (1) {

125 c = -1;

126 next = 0;

127 i = NR_TASKS;

128 p = &task[NR_TASKS];

// 这段代码也是从任务数组的最后一个任务开始循环处理,并跳过不含任务的任务槽。比较每个就绪

// 状态任务的counter(任务运行时间的递减滴答计数)值,哪一个值大,运行时间还不长,next 就

// 指向哪个的任务号。

129 while (--i) {

130 if (!*--p)

131 continue;

132 if ((*p)->state == TASK_RUNNING && (*p)->counter > c)

133 c = (*p)->counter, next = i;

134 }

// 如果比较得出有counter 值大于0 的结果,则退出124 行开始的循环,执行任务切换(141 行)。

135 if (c) break;

// 否则就根据每个任务的优先权值,更新每一个任务的counter 值,然后回到125 行重新比较。

// counter 值的计算方式为counter = counter /2 + priority。[右边counter=0??]

136 for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)

137 if (*p)

更多电子书教程下载请登陆http://down.zzbaike.com/ebook

本站提供的电子书教程均为网上搜集,如果该教程涉及或侵害到您的版权请联系我们。

第5 章 内核代码 linux/kernel/

103

138 (*p)->counter = ((*p)->counter >> 1) +

139 (*p)->priority;

140 }

141 switch_to(next); // 切换到任务号为next 的任务,并运行之。

142 }

143

// pause()系统调用。转换当前任务的状态为可中断的等待状态,并重新调度。

144 int sys_pause(void)

145 {

146 current->state = TASK_INTERRUPTIBLE;

147 schedule();

148 return 0;

149 }

150

// 把当前任务置为不可中断的等待状态,并让睡眠队列头的指针指向当前任务。

// 只有明确地唤醒时才会返回。该函数提供了进程与中断处理程序之间的同步机制。

// 函数参数*p 是放置等待任务的队列头指针。(参见列表后的说明)。

151 void sleep_on(struct task_struct **p)

152 {

153 struct task_struct *tmp;

154

// 若指针无效,则退出。(指针所指的对象可以是NULL,但指针本身不会为0)。

155 if (!p)

156 return;

157 if (current == &(init_task.task)) // 如果当前任务是任务0,则死机(impossible!)。

158 panic("task[0] trying to sleep");

159 tmp = *p; // 让tmp 指向已经在等待队列上的任务(如果有的话)。

160 *p = current; // 将睡眠队列头的等待指针指向当前任务。

161 current->state = TASK_UNINTERRUPTIBLE; // 将当前任务置为不可中断的等待状态。

162 schedule(); // 重新调度。

// 只有当这个等待任务被唤醒时,调度程序才又返回到这里,则表示被明确地唤醒。

163 if (tmp) // 若还存在等待的任务,则也将其置为就绪状态。

164 tmp->state=0;

165 }

166

// 将当前任务置为可中断的等待状态,并放入*p 指定的等待队列中。参见列表后对sleep_on()的说明。

167 void interruptible_sleep_on(struct task_struct **p)

168 {

169 struct task_struct *tmp;

170

171 if (!p)

172 return;

173 if (current == &(init_task.task))

174 panic("task[0] trying to sleep");

175 tmp=*p;

176 *p=current;

177 repeat: current->state = TASK_INTERRUPTIBLE;

178 schedule();

// 如果等待队列中还有等待任务,并且队列头指针所指向的任务不是当前任务时,则将该等待任务置为

// 可运行的就绪状态,并重新执行调度程序。当指针*p 所指向的不是当前任务时,表示在当前任务被放

// 入队列后,又有新的任务被插入等待队列中,因此,既然本任务是可中断的,就应该首先执行所有

// 其它的等待任务。

179 if (*p && *p != current) {

更多电子书教程下载请登陆http://down.zzbaike.com/ebook

本站提供的电子书教程均为网上搜集,如果该教程涉及或侵害到您的版权请联系我们。

第5 章 内核代码 linux/kernel/

104

180 (**p).state=0;

181 goto repeat;

182 }

// 下面一句代码有误,应该是*p = tmp,让队列头指针指向其余等待任务,否则在当前任务之前插入

// 等待队列的任务均被抹掉了。参见图4.3。

183 *p=NULL;

184 if (tmp)

185 tmp->state=0;

186 }

187

// 唤醒指定任务*p。

188 void wake_up(struct task_struct **p)

189 {

190 if (p && *p) {

191 (**p).state=0; // 置为就绪(可运行)状态。

192 *p=NULL;

193 }

194 }

时间: 2024-10-10 14:18:16

linux内核学习-5任务调度(关注新浪微博:寂寞侵蚀的岁月(4000多篇技术分享))的相关文章

linux内核学习-4kernal目录(关注新浪微博:寂寞侵蚀的岁月(4000多篇技术分享))

该目录下的代码文件从功能上可以分为三类,一类是硬件(异常)中断处理程序文件,一类是系统 调用服务处理程序文件,另一类是进程调度等通用功能文件.参见图1.5.我们现在根据这个分类方式, 从实现的功能上进行更详细的说明. 5.1.1.1 硬件中断处理类程序 主要包括两个代码文件:asm.s 和traps.c 文件.asm.s 用于实现大部分硬件异常所引起的中断的汇 编语言处理过程.而traps.c 程序则实现了asm.s 的中断处理过程中调用的c 函数.另外几个硬件中断 处理程序在文件system_

linux内核学习-6信号量(关注新浪微博:寂寞侵蚀的岁月(4000多篇技术分享))

#include // 调度程序头文件,定义了任务结构task_struct.初始任务0 的数据,// 还有一些有关描述符参数设置和获取的嵌入式汇编函数宏语句.8 #include // 内核头文件.含有一些内核常用函数的原形定义.9 #include // 段操作头文件.定义了有关段寄存器操作的嵌入式汇编函数.1011 #include // 信号头文件.定义信号符号常量,信号结构以及信号操作函数原型.1213 volatile void do_exit(int error_code); //

linux内核学习-3 main函数(关注新浪微博:寂寞侵蚀的岁月(4000多篇技术分享))

#ifdef RAMDISK // 如果定义了虚拟盘,则主内存将减少. 124 main_memory_start += rd_init(main_memory_start, RAMDISK*1024); 125 #endif // 以下是内核进行所有方面的初始化工作.阅读时最好跟着调用的程序深入进去看,实在看 // 不下去了,就先放一放,看下一个初始化调用 -- 这是经验之谈?. 126 mem_init(main_memory_start,memory_end); 127 trap_init

linux内核学习-3 init函数(关注新浪微博:寂寞侵蚀的岁月(4000多篇技术分享))

void init(void) 169 { 170 int pid,i; 171 172 setup((void *) &drive_info); // 读取硬盘参数包括分区表信息并建立虚拟盘和 // 安装根文件系统设备.(kernel/blk_drv/hd.c,71) 173 (void) open("/dev/tty0",O_RDWR,0); // 用读写访问方式打开设备"/dev/tty0", // 这里对应终端控制台. // 返回的句柄号0 -- s

Linux内核学习总结

李泽源 原创作品 转载请注明出处 <Linux内核分析>MOOC课程:http://mooc.study.163.com/course/USTC-1000029000 [Linux内核学习总结] 幸福来得很突然,这门课就快结束了…… 是时候,总结下这段时间的坚持了,也给同样对Linux内核有兴趣的你一个指南. 在这门课的学习过程中,按照老师的要求,每次课后都写一篇博文,这是一个很好的学习方式.每当写这些文章的时候,总是要多看几遍视频,再查查相关的资料,才能勉强凑成一个完整的文档:同时也把自己学

Linux内核学习总结(final)

Linux内核学习总结 符钰婧 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 这八周以来,我从拼不出来"Linux"这个词到知道了很多专有名词,也能大概了解Linux的工作机制,这一系列的进步都是一周周积累下来的.现在回过头来看,有种阳光总在风雨后的感觉,虽然这个比喻好像不太恰当. 闲话少说,接下来就进入这次的正题. 一.首先是对Linux操作系统的理解 1.操作系

Linux内核学习-进程

先说几个术语: 一.Linux进程的五个段 下面我们来简单归纳一下进程对应的内存空间中所包含的5种不同的数据区都是干什么的.重点:代码段.数据段.堆栈段,这是一个概念堆.栈.全局区.常量区,这是另一个概念1)代码段:代码段是用来存放可执行文件的操作指令,也就是说是它是可执行程序在内存中的镜像.代码段需要防止在运行时被非法修改,所以只准许读取操作,而不允许写入(修改)操作--它是不可写的.代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域.这部分

linux内核学习:进程管理

进程状态 TASK_RUNNING 可运行或正在运行 TASK_INTERRUPTIBLE 进程被阻塞,但可以被信号唤醒 TASK_UNINTERRUPTIBLE 进程被阻塞,且不可以被信号唤醒 TASK_STOPPED 进程已停止,且不能再投入运行 TASK_ZOMBIE 所谓的僵死进程,进程描述符仍然保留 关键函数和结构 task_struct thread_info current clone fork exec wait exit linux内核学习:进程管理,布布扣,bubuko.co

linux内核学习:中断

编程相关 注册中断 int request_irq( unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev) typedef irqreturn_t (*irq_handler_t)(int, void *); IRQF_DISABLED 会禁用除本本身以外的其它中断,一般是不用的 IRQF_SAMPLE_RANDOM 可以帮助内核随机数的产生.如果中断产生地毫无规律,可