java开发系统内核:实现进程优先级
2017-01-13 10:17
281 查看
更详细的讲解和代码调试演示过程,请参看视频
Linux kernel Hacker, 从零构建自己的内核
我们有了进程调度,目前来看,所有进程一律平等。我们的调度算法是遍历每一个进程,然后给每一个进程一定的运行时间,然后再切换下一个进程。但实际运用上,进程间不会是平等的,有些进程承担着比较重要的工作,因此,它有理由获得更多的运行时间,例如内核进程,一些进程不是很重要,同理,它就不应该占用过度的CPU资源。本节,我们要引入进程优先级的功能,让优先级高的进程获得更多的运行机会。
首先我们需要改动的是对TASK结构体的定义(multi_task.h):
我们增加了一个变量叫priority, 这个变量代表着进程的优先级,同时也是进程运行的时间片,这个值越大,进程获得的CPU运行时间就越多。TASK对象的相关处理函数也需要做相应改动,在multi_task.c中:
每个任务分配时,它的优先级会默认设置成100,也就是该任务能获得1秒的运行时间。task_run多增加了一个参数,也就是任务优先级,当一个任务准备加入调度队列时,需要指定它的优先级,在task_switch中,任务切换时,我们通过timer_settime来设置任务的运行时间,大家可以看到,时钟的长度设置为task->priority, 也就是说,任务的优先级同时也是任务的CPU运行时间。
任务激活的相关代码也需要做改动,任务可以对应一个数据队列,当队列有数据抵达时,队列会把存储在其中的任务加入调度队列,这个功能的实现是在golobal_define.c中,因此,我们也需要做相应改动:
当任务重新被激活时,我们传入的优先级数值是0,根据task_run的实现,当优先级数值为0时,任务保持原有优先级不变。最后需要改动的是主入口函数,在write_vga_desktop.c中:
我们为第一个任务分配的优先级是5,第二个任务的优先级是10,也就是第二个任务得到的CPU时间是第一个任务的2倍。将上面代码编译运行时可以得到下面结果:
我们可以看到,第二个窗口计数数值大概是第一个窗口的2倍,这是因为第二个窗口对应的进程获得的CPU运行时间是第一个窗口两倍的缘故。
本节代码比较简单,这是为了下一次实现更复杂的进程调度功能:优先级队列做准备的,通过视频可以获得更加详细的代码讲解和演示效果。
更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号:
Linux kernel Hacker, 从零构建自己的内核
我们有了进程调度,目前来看,所有进程一律平等。我们的调度算法是遍历每一个进程,然后给每一个进程一定的运行时间,然后再切换下一个进程。但实际运用上,进程间不会是平等的,有些进程承担着比较重要的工作,因此,它有理由获得更多的运行时间,例如内核进程,一些进程不是很重要,同理,它就不应该占用过度的CPU资源。本节,我们要引入进程优先级的功能,让优先级高的进程获得更多的运行机会。
首先我们需要改动的是对TASK结构体的定义(multi_task.h):
struct TASK { int sel, flags; int priority; struct TSS32 tss; };
我们增加了一个变量叫priority, 这个变量代表着进程的优先级,同时也是进程运行的时间片,这个值越大,进程获得的CPU运行时间就越多。TASK对象的相关处理函数也需要做相应改动,在multi_task.c中:
struct TASK *task_init(struct MEMMAN *memman) { .... task = task_alloc(); task->flags = 2; //active task->priority = 100; taskctl->running = 1; taskctl->now = 0; taskctl->tasks[0] = task; load_tr(task->sel); task_timer = timer_alloc(); timer_settime(task_timer, task->priority); return task; .... } void task_run(struct TASK *task, int priority) { if (priority > 0) { task->priority = priority; } task->flags = 2; taskctl->tasks[taskctl->running] = task; taskctl->running++; return; } void task_switch(void) { struct TASK *task; if (taskctl->running >= 2) { taskctl->now++; if (taskctl->now == taskctl->running) { taskctl->now = 0; } task = taskctl->tasks[taskctl->now]; timer_settime(task_timer, task->priority); farjmp(0, taskctl->tasks[taskctl->now]->sel); } return; }
每个任务分配时,它的优先级会默认设置成100,也就是该任务能获得1秒的运行时间。task_run多增加了一个参数,也就是任务优先级,当一个任务准备加入调度队列时,需要指定它的优先级,在task_switch中,任务切换时,我们通过timer_settime来设置任务的运行时间,大家可以看到,时钟的长度设置为task->priority, 也就是说,任务的优先级同时也是任务的CPU运行时间。
任务激活的相关代码也需要做改动,任务可以对应一个数据队列,当队列有数据抵达时,队列会把存储在其中的任务加入调度队列,这个功能的实现是在golobal_define.c中,因此,我们也需要做相应改动:
int fifo8_put(struct FIFO8 *fifo, unsigned char data) { .... if (fifo->task != 0) { if (fifo->task->flags != 2) { task_run(fifo->task, 0); } } .... }
当任务重新被激活时,我们传入的优先级数值是0,根据task_run的实现,当优先级数值为0时,任务保持原有优先级不变。最后需要改动的是主入口函数,在write_vga_desktop.c中:
void CMain(void) { .... for (i = 0; i < 2; i++) { .... task_run(task_b[i], (i+1)*5); ... } .... }
我们为第一个任务分配的优先级是5,第二个任务的优先级是10,也就是第二个任务得到的CPU时间是第一个任务的2倍。将上面代码编译运行时可以得到下面结果:
我们可以看到,第二个窗口计数数值大概是第一个窗口的2倍,这是因为第二个窗口对应的进程获得的CPU运行时间是第一个窗口两倍的缘故。
本节代码比较简单,这是为了下一次实现更复杂的进程调度功能:优先级队列做准备的,通过视频可以获得更加详细的代码讲解和演示效果。
更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号:
相关文章推荐
- java开发系统内核:实现进程优先级队列
- java开发系统内核:实现进程自动切换,再现Linus当年辉煌一刻
- java开发系统内核:进程初体验及代码其实现1
- java开发系统内核:cls 屏幕清空命令的实现
- java开发系统内核:实现type命令读取文件内容
- java开发系统内核:实现回车键的处理
- java开发系统内核:使用LDT保护进程数据和代码
- java开发系统内核:自动化进程切换
- java开发系统内核:实现shift按键效果
- java开发系统内核:依靠多任务实现多窗口
- java开发系统内核:实现基于FAT12文件系统的dir命令
- java开发系统内核:像Linux一样使用中断实现内核API
- java开发系统内核:实现窗口创建API,由DOS进入windows
- java开发系统内核:实现鼠标与窗口的互操作
- java开发操作系统内核:实现进程的优先级切换
- java开发系统内核:实现系统API调用
- java开发系统内核:使用一个中断实现多个API调用
- java开发系统内核:进程的挂起和恢复
- java开发系统内核:实现应用程序和内核间的控制权切换
- java开发系统内核:实现窗口图形绘制API