这一节可以很长,也可以很短.要写长是因为这里有不少细节可以写,要写短是因为如果不关注细节,而只关注基本的原理,那么几句话就可以说完了.
坦白的说,细节部分我还没有完全吃透,即使是<<深入理解Linux内核>>一书,讲到这部分也费了不少篇幅.因为我在第一遍阅读时阅读速度要尽可能的加快,一些不太明白的细节暂且放过去,等精读第一遍完毕了再继续深入,所以我选择了长话短说.
switch_to宏用于进程切换,给定了前一个进程结构体指针prev,以及需要切换到的进程结构体指针next,从prev切换到next.
但是,实际上,switch_to宏有三个参数,除了上面说的两个参数之外,还有一个last参数.而且使用switch_to宏的时候传入的prev和last都是同一个值,比如会这么调用这个宏:
switch_to(prev,next,prev).
这是为什么呢?
考虑一种场景,进程A切换到进程B,因为每个进程的空间是不同的,所以在切换之前,进程A的空间里prev=A,next=B,last=A.
一段时间之后,需要切换回到进程A,假设当前进程是C,那么对于C而言prev=C,next=A,last=C.
对比前后两种场景:
进程A切换前:prev=A,next=B,last=A
进程C切换前:prev=C,next=A,last=C
这时开始从进程C切换到进程A,注意到在切换之前switch_to宏将prev存放到了eax寄存器中,也就是在进程C切换到进程A之前,eax=C
切换之后,很显然,来到了进程A的空间,因此prev,next,last指针要回到进程A被切换出去之前的指向,因此prev=A,next=B,last=A,而eax的数据保持不变.
在switch_to宏返回之前,将eax寄存器的数据存放到last中,因此,last=eax=C.
此时,也就是进程A被切换回来之后,prev=A,next=B,last=C
从上面的分析可以看出,实际上,prev指向的是进程切换之前被切换走的进程指针,而last指向的是切换之后从哪个进程切换过来的.
两者的意义并不一样,只不过是在切换之后原先的prev无用了,可以用于保存切换之后是从哪个进程切换过来的,所以才会出现调用switch_to宏时prev和last相同的情况.