1.进程切换首先要进行用户空间的切换,即将新进程页面目录的起始物理地址装入控制寄存器CR3.
static inline void switch_mm(struct mm_struct *prev,
struct mm_struct *next,
struct task_struct *tsk,
unsigned cpu)
{
......
asm volatile("movl %0, %%cr3": : "r" (__pa(next->pgd)));
....
}
值得注意的是此时cpu在系统空间内运行,所有进程的页面目录中与系统空间相对应的目录项都指向相同的目录表,所以每一个进程都有相同的页面目录。
2.然后进行堆栈的切换。
#define switch_to(prev, next, last) do { \
asm volatile("pushl %%esi \n\t" \
"pushl %%ebi \n\t" \
"pushl %%ebp \n\t" \
"movl %%esp, %0 \n\t" \ // save ESP for prev
"movl %3,%%esp \n\t" \ // restore ESP to next
"movl $1f, %1 \n\t" \ // set EIP for prev
"pushl %4 \n\t" \ // restore EIP for next, which is $1f
"jump __switch_to \n" \ // ret and set EIP to %4
"1:\t" \
"popl %%ebp \n\t" \
"popl %%ebi \n\t" \
"popl %%esi \n\t" \
:"=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)