linux内核学习-5任务调度(关注新浪微博:寂寞侵蚀的岁月(4000多篇技术分享))
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 }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。