嵌入式操作系统内核原理和开发(改进型优先级调度)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
嵌入式操作系统内核原理和开发(改进型优先级调度)
上面的一篇博客说到了优先级调度,但是那个优先级调度算法比较极端。
打个比方说,现在王先生有三个小孩,分别是老大、老二、老三。
假设现在到了饭点,王先生需要给三个小孩喂饭。
此时如果是时间片轮转的话,那么就是绝对公平,王先生每人一口不停地进行喂饭。
如果是优先级调度,那么王先生首先自己有一个优先级考量,比如说三个小孩按照年龄顺序优先级是逐渐提高的,毕竟小孩需要更多的照顾嘛。
这个时候如果需要进行喂饭的话,那么王先生需要首先伺候好最小的那个小孩老三,才会有时间照顾老二,至于老大什么时候才能得到照顾那就看造化了。
现在,我们打算重新换一种方法。
假设三个小孩的优先级分别是1、2、3,其中年龄越小优先级越高,3代表高优先级。
接着,我们按照优先级给三个小孩安排时间片,分别是1、2、3。
同时,这个时间片不光代表了当前可用的剩余时间,还代表了小孩此时的临时优先级。
(1)首先王先生给老三喂饭,时间片降低1,即临时优先级为2;
(2)接着王先生判断当前优先级最高的仍为老三,毕竟老二的优先级也没有超过老三,所以老三的时间片降1,临时优先级为1;
(3)王先生获知当前优先级最高的为老二,老二获得时间片;
(4)此时王先生发现三个孩子的临时优先级都一样,那么就会按照固定优先级的大小依次对老三、老二、老大进行喂饭。
我们发现,这中间受益最大的就是老二。
当然,我们可以做进一步推论,如果老王的孩子越多,那么优先级处于中间的孩子在时间片的分配上将更加均匀,响应也会更加及时,交互性也会变得很好。
根据以上的想法,我们重新改写了优先级调度算法,修改为改进型优先级调度算法,
1int find_next_thread()
2{
3int index;
4int choice = THREAD_MAX_NUMBER -1;
5int value = gAllTask[choice].time_slice;
6
7for(index = choice -1; index >= 0; index --)
8 {
9if(value < gAllTask[index].time_slice)
10 {
11 choice = index;
12 value = gAllTask[index].time_slice;
13 }
14 }
15
16if(0 == value)
17 choice = -1;
18
19return choice;
20}
21#define TIME_ROUND_SCHEDULE 0
22#define HARD_PRIORITY_SCHEDULE 0
23#define SOFT_PRIORITY_SCHEDULE 1
这些代码都是可以在系统中共存的。
选用什么算法,取决于实际情况是什么样的情形。
24#include <stdio.h>
25#include <time.h>
26#include <stdlib.h>
27#include <signal.h>
28#include <assert.h>
29#include <string.h>
30#include <sys/time.h>
31
32#define UINT32 unsigned int
33#define STACK_LENGTH 512
34#define THREAD_MAX_NUMBER 10
35#define TIME_ROUND_SCHEDULE 0
36#define HARD_PRIORITY_SCHEDULE 0
37#define SOFT_PRIORITY_SCHEDULE 1
38
39typedef struct _TASK_INFO
40{
41UINT32 id;
42UINT32* stack;
43UINT32 size;
44UINT32 context;
45UINT32 priority;
46UINT32 time_slice;
47void (*func)();
48
49}TASK_INFO;
50
51static struct itimerval oldtv;
52UINT32 old = 0;
53UINT32 count = 0;
54UINT32 task_stack[THREAD_MAX_NUMBER][STACK_LENGTH] = {0}; 55TASK_INFO gAllTask[THREAD_MAX_NUMBER] = {0};
56UINT32 current_thread_id = 0;
57
58void set_timer()
59{
60struct itimerval itv;
61 itv.it__sec = 1;
62 itv.it__usec = 0;
63 itv.it__sec = 1;
64 itv.it__usec = 0;
65 setitimer(ITIMER_REAL, &itv, &oldtv);
66}
67
68void swap(UINT32* prev, UINT32* next)
69{
70 __asm("push %%eax\n\t"
71"push %%ebx\n\t"
72"push %%ecx\n\t"
73"push %%edx\n\t"
74"push %%esi\n\t"
75"push %%edi\n\t"
76"push %%ebp\n\t"
77"push %%esp\n\t"
78"lea 0x8(%%ebp), %%eax\n\t"
79"mov (%%eax), %%eax\n\t"
80"mov %%esp, (%%eax)\n\t"
81
82"lea 0xc(%%ebp), %%eax\n\t"
83"mov (%%eax), %%eax\n\t"
84"mov (%%eax), %%esp\n\t"
85"pop %%esp\n\t"
86"pop %%ebp\n\t"
87"pop %%edi\n\t"
88"pop %%esi\n\t"
89"pop %%edx\n\t"
90"pop %%ecx\n\t"
91"pop %%ebx\n\t"
92"pop %%eax\n\t"
93 ::);
94}
95
96void hello()
97{
98int temp = 0;
99
100while(1) {
101 printf("id = %d, temp = %d, count = %d in
thread!\n",current_thread_id, temp ++, count ++);
102 swap(&gAllTask[current_thread_id].context, &old); 103
104 printf("id = %d, temp = %d, count = %d in
thread!\n",current_thread_id, temp ++, count ++);
105 swap(&gAllTask[current_thread_id].context, &old); 106 }
107}
108
109#if HARD_PRIORITY_SCHEDULE
110int find_next_thread()
111{
112int index;
113
114for(index = THREAD_MAX_NUMBER -1; index >=0; index --) 115 {
116if(0 != gAllTask[index].time_slice)
117break;
118 }
119
120return index;
121}
122
123#endif
124
125
126#if SOFT_PRIORITY_SCHEDULE
127int find_next_thread()
128{
129int index;
130int choice = THREAD_MAX_NUMBER -1;
131int value = gAllTask[choice].time_slice;
132
133for(index = choice -1; index >= 0; index --)
134 {
135if(value < gAllTask[index].time_slice)
136 {
137 choice = index;
138 value = gAllTask[index].time_slice;
139 }
140 }
141
142if(0 == value)
143 choice = -1;
144
145return choice;
146}
147
148#endif
149
150void reset_time_slice ()
151{
152int index;
153
154for(index = 0; index < THREAD_MAX_NUMBER; index++)
155 gAllTask[index].time_slice = gAllTask[index].priority + 1; 156}
157
158void task_init(int index)
159{
160UINT32 unit = gAllTask[index].size;
161UINT32* pData = gAllTask[index].stack;
162
163 memset((void*)pData,(int) 0, unit * sizeof(UINT32));
164 pData[unit -1] = (UINT32) gAllTask[index].func;
165 pData[unit -2] = 0;
166 pData[unit -3] = 0;
167 pData[unit -4] = 0;
168 pData[unit -5] = 0;
169 pData[unit -6] = 0;
170 pData[unit -7] = 0;
171 pData[unit -8] = 0;
172 pData[unit -9] = 0;
173 pData[unit -10] = (UINT32) &pData[unit - 9];
174 gAllTask[index].context = (UINT32) &pData[unit -10];
176
177#if TIME_ROUND_SCHEDULE
178void signal_handler(int m)
179{
180 current_thread_id = current_thread_id % THREAD_MAX_NUMBER; 181 swap(&old, &gAllTask[current_thread_id].context);
182 current_thread_id ++;
183}
184
185#else
186void signal_handler(int m)
187{
188int index;
189
190start:
191 index = find_next_thread();
192if(-1 == index)
193 {
194 reset_time_slice();
195goto start;
196 }
197
198 gAllTask[index].time_slice --;
199 current_thread_id = index;
200 swap(&old, &gAllTask[current_thread_id].context);
201}
202#endif
203
204
205void set_all_task()
206{
207int index;
208 memset(gAllTask, 0, sizeof(gAllTask));
209
210for(index = 0; index < THREAD_MAX_NUMBER; index ++)
211 {
212 gAllTask[index].id = index;
213 gAllTask[index].stack = task_stack[index];
214 gAllTask[index].size = STACK_LENGTH;
215 gAllTask[index].context = 0;
216 gAllTask[index].func = hello;
217 gAllTask[index].priority = index;
218 gAllTask[index].time_slice = index + 1;
220 task_init(index);
221 }
222}
223
224int main()
225{
226char val;
227
228 set_all_task();
229 set_timer();
230 signal(SIGALRM, signal_handler); 231
232while(1)
233 {
234 scanf("%c", &val);
235 }
236
237 exit(0);
238return 1;
239}。