Chinaunix首页 | 论坛 | 博客
  • 博客访问: 58490
  • 博文数量: 13
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 130
  • 用 户 组: 普通用户
  • 注册时间: 2015-04-26 15:04
文章分类

全部博文(13)

文章存档

2015年(13)

我的朋友

分类: LINUX

2015-05-11 13:11:27


点击(此处)折叠或打开

  1. [schedule()>switch_to()]
  2. 15 #define switch_to(prev,next,last) do { \
  3. 16 asm volatile("pushl %%esi\n\t" \
  4. 17 "pushl %%edi\n\t" \
  5. 18 "pushl %%ebp\n\t" \
  6. 19 "movl %%esp,%0\n\t"/* save ESP */ \
  7. 20 "movl %3,%%esp\n\t"/* restore ESP */ \
  8. 21 "movl $1f,%1\n\t" /* save EIP */ \
  9. 22 "pushl %4\n\t" /* restore EIP */ \
  10. 23 "jmp __switch_to\n" \
  11. 24 "1:\t" \
  12. 25 "popl %%ebp\n\t" \
  13. 26 "popl %%edi\n\t" \
  14. 27 "popl %%esi\n\t" \
  15. 28 :"=m" (prev->thread.esp),"=m" (prev->thread.eip), \
  16. 29 "=b" (last) \
  17. 30 :"m" (next->thread.esp),"m" (next->thread.eip), \
  18. 31 "a" (prev), "d" (next), \
  19. 32 "b" (prev)); \
  20. 33 } while (0)
《情景分析》里在这段代码上费了不小的篇幅,已经算得上很合格的解读了,但没有书中惯有的锋利。所以补上一些“锋利”的看法:

1, 第22行和23行
push %4
jmp __switch_to

  这两句的可读性并不好,改写成:
call __switch_to
jmp dword  [next->thread.eip]          //我没用at&t语法
  效果是一样的。内核中像这样的push b, jmp  a还不止一处,大概是为了效率。而且,对汇编熟的人,可能反而喜爱这种写法,这样写,就像是一个“双连跳”。就仿佛是jmp的目标不是函数,而是一段普通的代码,在其末尾,还有一个臆想的"jmp b"。push b是伏笔。
  这种模型抽象还是很清晰的,估计自己以后也会试着用。

2,还是这两行
  知道这两行的功能,可能立即又陷入一个误区:jmp __switch_to,jmp next->thraed.eip,看样子,是跳向了新的代码了。嗯,也是也是,肯定是执行next进程的指令去了。
  其实不是的。这里的jmp next->thread.eip,几乎总是跳向这段代码里的"1f"标签。没有跳走。
  像switch_to这种,它的代码是公用的,不属于某个进程。
  那为什么要跳呢?直接写成call __switch_to,等__switch_to返回,自然而然的走到"1f"标签多好。
  前面说的是“通常”,如果next是一个新进程,它没有被调度过,即使我们预先把它的thread.eip设置成,"$1f",他的内核中没有上下文,1f标签处的那些pop..pop..对它是无从谈起的。
  对一个新进程,还是让它干干净净的restore_all最好。
  所以,jmp next->thread.eip,也就是那个push next->thread.eip,是为了代码的普适性。如果只考虑一般情况,那这两句精简成一句“call __switch_to”是没问题的。

  3,为什么只保存esi,edi,ebp这三个寄存器呢?
阅读(1531) | 评论(0) | 转发(0) |
0

上一篇:pregs VS. switch

下一篇:调通了ring3进程

给主人留下些什么吧!~~