免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2845 | 回复: 2
打印 上一主题 下一主题

[进程管理] 已解决 关于进程调度schedule的疑问 [复制链接]

论坛徽章:
1
双子座
日期:2013-11-06 17:18:01
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-12-31 16:43 |只看该作者 |倒序浏览
本帖最后由 seufy88 于 2017-01-01 12:43 编辑

内核版本: LINUX 2.4.0平台: X86 SMP多CPU场合

部分代码:
  1. asmlinkage void <b>schedule</b>(void)

  2. next = idle_task(this_cpu);
  3.         c = -1000;
  4.         if (prev->state == TASK_RUNNING)
  5.                 goto still_running;

  6. still_running_back:
  7.         list_for_each(tmp, &runqueue_head) {
  8.                 p = list_entry(tmp, struct task_struct, run_list);
  9.                 if (<b>can_schedule</b>(p, this_cpu)) {
  10.                         int weight = goodness(p, this_cpu, prev->active_mm);
  11.                         if (weight > c)
  12.                                 c = weight, next = p;
  13.                 }
  14.                
  15.                
  16. #ifdef CONFIG_SMP
  17. <b>         next->has_cpu = 1;</b>
  18.         next->processor = this_cpu;
  19. #endif


  20. switch_to(prev, next, prev);
  21.         __schedule_tail(prev);
复制代码
  1. #define can_schedule(p,cpu) ((!(p)->has_cpu) && \
  2.                                 ((p)->cpus_allowed & (1 << cpu)))
复制代码


  1. static inline void __schedule_tail(struct task_struct *prev)
  2. {
  3. #ifdef CONFIG_SMP

  4. <b>        prev->has_cpu = 0;</b>
复制代码


疑问:
has_cpu表示该进程正被某个CPU占用,是禁止被调度的。
当前进程(prev)调用switch_to切换出去时,为什么只将next的has_cpu设为1,而自己的has_cpu没有被清为0?
那prev的has_cpu一直为1的情况下,难道不是一直不会被调度从而切换回来吗
prev不再从switch_to被切换回来时,那在__schedule_tail中将prev的has_cpu清0是否妥当?
一个进程A在已经占用CPU的情况下,schedule到其他进程,但进程A没有清除自己的has_cpu (=0)
而has_cpu等于1的情况下是不允许被调度的,所以进程A不会在被调度回来
而进程A的has_cpu清零被安排在了切换回来后的__schedule_tail中
这是否有个矛盾在里面?






论坛徽章:
1
双子座
日期:2013-11-06 17:18:01
2 [报告]
发表于 2016-12-31 19:42 |只看该作者
本帖最后由 seufy88 于 2016-12-31 19:50 编辑

问题2:
  1. #define switch_to(prev,next,last) do {                                        \
  2.         asm volatile("pushl %%esi\n\t"                                        \
  3.                      "pushl %%edi\n\t"                                        \
  4.                      "pushl %%ebp\n\t"                                        \
  5.                      "movl %%esp,%0\n\t"        /* save ESP */                \
  6.                      "movl %3,%%esp\n\t"        /* restore ESP */        \
  7.                      "movl $1f,%1\n\t"                /* save EIP */                \
  8.                      "pushl %4\n\t"                /* restore EIP */        \
  9.                      "jmp __switch_to\n"                                \
  10.                      "1:\t"                                                \
  11.                      "popl %%ebp\n\t"                                        \
  12.                      "popl %%edi\n\t"                                        \
  13.                      "popl %%esi\n\t"                                        \
  14.                      :"=m" (prev->thread.esp),"=m" (prev->thread.eip),        \
  15.                       "=b" (last)                                        \
  16.                      :"m" (next->thread.esp),"m" (next->thread.eip),        \
  17.                       "a" (prev), "d" (next),                                \
  18.                       "b" (prev));                                        \
  19. } while (0)
复制代码


在jmp到__switch_to这个函数后,它需要2个参数,而根据switch_to宏中的内容,发现是edi,ebp这2个寄存器被压入栈中,来充当__switch_to的参数
但这为2个内容为什么可以当作prev_p和next_p呢?
  1. void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
复制代码

论坛徽章:
1
双子座
日期:2013-11-06 17:18:01
3 [报告]
发表于 2017-01-01 10:53 |只看该作者
本帖最后由 seufy88 于 2017-01-01 11:00 编辑

第一个问题,已解决。
  1. #define switch_to(prev,next,last) do {                                        \
  2.         asm volatile("pushl %%esi\n\t"                                        \
  3.                      "pushl %%edi\n\t"                                        \
  4.                      "pushl %%ebp\n\t"                                        \
  5.                      "movl %%esp,%0\n\t"        /* save ESP */                \
  6.                      "movl %3,%%esp\n\t"        /* restore ESP */        \
  7.                      "movl $1f,%1\n\t"                /* save EIP */                \
  8.                      "pushl %4\n\t"                /* restore EIP */        \
  9.                      "jmp __switch_to\n"                                \
  10.                      "1:\t"                                                \
  11.                      "popl %%ebp\n\t"                                        \
  12.                      "popl %%edi\n\t"                                        \
  13.                      "popl %%esi\n\t"                                        \
  14.                      :"=m" (prev->thread.esp),"=m" (prev->thread.eip),        \
  15.                       "=b" (last)                                        \
  16.                      :"m" (next->thread.esp),"m" (next->thread.eip),        \
  17.                       "a" (prev), "d" (next),                                \
  18.                       "b" (prev));                                        \
  19. } while (0)
复制代码
进程A切换到进程B,在内核栈从A变成B后,该嵌入汇编最后会将EBX寄存器的内容赋值给LAST变量,而EBX又是输入寄存器,在整个SWITCH过程中并不改,一直存放着PREV的内容,注意这里的PREV是进程A的内核栈上的内容。也就是进程A的current
在执行完SWITCH的最后,将EBX赋值给LAST变量,而由于内核栈已经切换到B,这里的LAST变量虽然也是栈上的局部变量,但已经是进程B栈上的了。
所以切换到B后,对B来讲PREV局部变量中已经是存放着上一个被切过来的进程A的TAKS_struct了。接着调用schedule_tail,传入RREV,将进程A的has_cpu清0,让进程A将来可以再次被调度。

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP