关于进程切换

发布于 2022-07-21 23:41:45 字数 4530 浏览 19 评论 7

以下是2.4.0内核中switch_to的定义:

#define switch_to(prev,next,last) do {                                       
        asm volatile("pushl %%esint"                                       
17:                     "pushl %%edint"                                       
18:                     "pushl %%ebpnt"                                       
                     "movl %%esp,%0nt"        /* save ESP */               
                     "movl %3,%%espnt"        /* restore ESP */       
                     "movl $1f,%1nt"                /* save EIP */               
                     "pushl %4nt"                /* restore EIP */       
23:                     "jmp __switch_ton"                               
                     "1:t"                                               
                     "popl %%ebpnt"                                       
                     "popl %%edint"                                       
                     "popl %%esint"                                       
                     :"=m" (prev->thread.esp),"=m" (prev->thread.eip),       
                      "=b" (last)                                       
                     :"m" (next->thread.esp),"m" (next->thread.eip),       
                      "a" (prev), "d" (next),                               
                      "b" (prev));                                       
} while (0)

它在23行通过jmp __switch_to“调用”函数__switch_to(),其原型为
       
        void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)

结合switch_to的17和18行,可知next_p的值原在edi中,prev_p在ebp中。

但switch_to的输入部却表明,prev_p是在eax及ebx中,next_p是在edx中。请问这是怎么回事。谢谢

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

恋你朝朝暮暮 2022-07-26 12:11:46

asm-i386/system.h中定义的
void FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));

陈独秀 2022-07-26 07:13:23

多谢seanseu兄的热心帮助。不过2.4.0内核中是这样定义__switch_to的:
void __switch_to(struct task_struct *prev_p,struct task_struct *next_p),
并未将它定义成fastcall啊。这是怎么回事呢?谢谢

万水千山粽是情ミ 2022-07-25 18:20:56

关于eflags寄存器的保存,我看了一下2.6.11的代码,其中switch_to已经做出了如下修改:
#define switch_to(prev,next,last) do {                                 
16         unsigned long esi,edi;                                          
17         asm volatile("pushflnt"                                       
18                      "pushl %%ebpnt"                                 
19                      "movl %%esp,%0nt"        /* save ESP */         
20                      "movl %5,%%espnt"        /* restore ESP */      
21                      "movl $1f,%1nt"          /* save EIP */         
22                      "pushl %6nt"             /* restore EIP */      
23                      "jmp __switch_ton"                                
24                      "1:t"                                             
25                      "popl %%ebpnt"                                   
26                      "popfl"                                            
27                      :"=m" (prev->thread.esp),"=m" (prev->thread.eip),  
28                       "=a" (last),"=S" (esi),"=D" (edi)                 
29                      :"m" (next->thread.esp),"m" (next->thread.eip),   
30                       "2" (prev), "d" (next));                          
31 } while (0)

可以看到esi,edi寄存器已经改为通过局部变量保存,而且增加了pushflnt,保存了eflags.关于这点我也比较疑惑,似乎和编译器有关,或者与__switch_to有关,没有仔细研究,不知有大侠是否有研究.另外,把esi和edi改为局部变量保存也是有原因的,不知有人是否知道.似乎与2.6内核的压栈出栈有关.

傲世九天 2022-07-25 14:19:57

struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct task_struct *next_p),这个是__switch_to的函数定义,关于寄存器传值,可以去看一下fastcall的说明.也就是regparm(3)的说明

演多会厌 2022-07-24 18:36:45

谢谢。那么请问,编译器在编译__switch_to()时,遇到prev_p就应该编译为eax或ebx,遇到next_p就应该编译为edx.编译器是怎样做到这一点的呢?因为在__switch_to()中并未对编译规则作出说明啊

淡水深流 2022-07-22 18:34:42

那么ecx和eflags寄存器为什么不保存呢?
默认的参数传递都是什么?什么时候是通过寄存器,什么时候通过堆栈?
另外__switch_to中只看到加载next进程调试寄存器的操作,却没有保存prev进程的调试寄存器,why?

叹倦 2022-07-22 04:53:36

__switch_to参数并不是通过stack传递的,而是通过寄存器传,所以prev_p是在eax及ebx中,next_p是在edx中。一开始的三个push只是保存该进程的这三个寄存器。因为编译器假定这三个寄存器在switch_to中是不改变的。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文