linux内核中的线程是用进程模拟的——LWP轻量级进程——linux的进程和线程都是task结构体。一个进程就是一组task的集合——用双向链表互相链接,所有task的成员group_leader指向主线程的task地址。tgid就是进程号,pid是线程号。tgid相同的task属于同一进程,和tgid相同的pid是主线程,其他是普通线程。
在linux的调度器眼里只能看到task的结构体,那么如何区分是进程间切换或是线程间切换呢? 比如A进程的a线程要切换到B进程的b线程,如何识别?再比如A进程a线程要切换到A进程的另一个线程,又如何识别?
难道是根据页表地址不同来确定是进程间切换?不对。搜了下,是比较task的成员mm的地址来识别的。 如果旧task的mm与即将运行的task的mm地址是同一个说明就是线程间切换,否则就是进程间切换,走的流程就不一样了。
详情如下
调度器切换会调用context_switch,而它会调用switch_mm,搜了context_switch的相关代码片段:
if (!mm)
{
/* 要运行的task是内核线程走这里 /
}
else
{
/ 不是内核线程, 则需要切换虚拟地址空间 */
switch_mm(oldmm, mm, next);
}
而switch_mm函数的部分代码片段如下:
if (likely(prev != next))
{
/* 执行进程间切换流程 /
}
else
{
/ 执行线程间切换流程 */
}
prev就是上个代码片段的oldmm,next就是上个代码片段的mm。
可见确实是比较task的mm成员来确定是进程间切换还是线程间切换的。