linux-0.11内核源码——(一)内核进程调度分析

本文解析了Linux0.11内核中的系统进程运行机制,重点介绍了Jiffies时钟滴答、定时器中断服务函数以及_do_timer函数的工作原理,探讨了task_struct结构在进程创建和调度中的作用,以及基于优先级的时间片轮转调度算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

附上linux-0.11内核地址https://mirrors.edge.kernel.org/pub/linux/kernel/Historic/old-versions/

系统进程的运转方式

CPU内部有一个RTC,会在上电的时候调用nktime函数算出从1970年1月1日0时开始到当前开机点所过的秒数给MKTIME函数传来的时间结构体的赋值。

由初始化时从RTC(coms)中读出的参数转化为时间存入全局变量中,并且会为JIFFIES所用。JIFFIES是一个系统的时钟滴答,一个系统滴答是10ms ,定时器10ms一个滴答-->每隔10ms会引发一个定时器中断。中断服务函数,如下,首先会进行JIFFIES的自加

kernel\system_call.s下

  1. _timer_interrupt:
  2. push %ds # save ds,es and put kernel data space
  3. push %es # into them. %fs is used by _system_call
  4. push %fs
  5. pushl %edx # we save %eax,%ecx,%edx as gcc doesn't
  6. pushl %ecx # save those across function calls. %ebx
  7. pushl %ebx # is saved as we use that in ret_sys_call
  8. pushl %eax
  9. movl $0x10,%eax
  10. mov %ax,%ds
  11. mov %ax,%es
  12. movl $0x17,%eax
  13. mov %ax,%fs
  14. incl _jiffies #jiffies自加
  15. movb $0x20,%al # EOI to interrupt controller #1
  16. outb %al,$0x20
  17. movl CS(%esp),%eax
  18. andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor)
  19. pushl %eax
  20. call _do_timer #调用_do_timer函数
  21. addl $4,%esp # task switching to accounting ...
  22. jmp ret_from_sys_call

上面的jiffies的中断服务函数调用_do_timer 函数 

  1. void do_timer(long cpl)
  2. {
  3. extern int beepcount;
  4. extern void sysbeepstop(void);
  5. if (beepcount)
  6. if (!--beepcount)
  7. sysbeepstop();
  8. //cpl表示当前被中断的进程所储存的状态是内核态还是用户态
  9. //0表示被中断的是内核进程,1表示被中断的是用户进程
  10. if (cpl)
  11. current->utime++; /*current为宏定义指当前进程*/
  12. else
  13. current->stime++;
  14. if (next_timer) {
  15. next_timer->jiffies--;
  16. while (next_timer && next_timer->jiffies <= 0) {
  17. void (*fn)(void);
  18. fn = next_timer->fn;
  19. next_timer->fn = NULL;
  20. next_timer = next_timer->next;
  21. (fn)();
  22. }
  23. }
  24. if (current_DOR & 0xf0)
  25. do_floppy_timer();
  26. if ((--current->counter)>0) return;
  27. current->counter=0;
  28. if (!cpl) return;
  29. schedule();
  30. }

上述current是一个宏定义全局变量,转到定义处是调用的task_struct结构体。

struct task_struct *current = &(init_task.task);

 进程的创建使用等都是在和task_struct这个结构体打交道,进程的创建就是创建一个task_struct对象,然后再对该对象赋值。一个task_struct对应一个进程,所以task_struct[n] 

对应一个进程向量表,每一个进程都有一个变量叫counter为时间片。counter在进程调度时会使用。进程的调度就是task_struct[n]链表的检索,去找时间片最大的任务调用(长任务优先算法)。直到counter为0,然后再进行新一轮的调用。当所有进程task_struct[n]的时间片都为0时,则重新为每个进程分配时间片kernel\sched.c下时间片分配方式如下:

(*p)->counter = ((*p)->counter >> 1) + (*p)->priority;

分配时就会涉及优先级,将优先级加到时间片上去,优先级高的时间片就大,时间片大就先调度。所以0.11的内核就是优先级时间片轮转调度算法

上述do_timer函数中next_timer定义如下:

  1. static struct timer_list {
  2. long jiffies;
  3. void (*fn)();
  4. struct timer_list * next;
  5. } timer_list[TIME_REQUESTS], * next_timer = NULL;

这是一个结构体链表,是时间链表的指针。next_timer是嫁接与jiffies变量的所有定时器的事件链表。jiffies就像一个时间轴,你可以选择在时间轴上任意一点触发一个事件。这个时间轴就像定时器链表,可以管理嫁接在这上面的定时器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

举报

选择你想要举报的内容(必选)
  • 内容涉黄
  • 政治相关
  • 内容抄袭
  • 涉嫌广告
  • 内容侵权
  • 侮辱谩骂
  • 样式问题
  • 其他
点击体验
DeepSeekR1满血版
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回顶部

登录后您可以享受以下权益:

×