进程切换switch_to()注释

进程切换前需要做准备工作,其中对于内核进程和用户进程在切换地址空间中的处理方式是不同的,主要因为内核进程只使用内核地址空间,而linux的内核地址空间是固定的,但用户进程就不一样了,而内核会借用用户的地址空间,mm_struct中的页表信息在tlb中是有缓存的,这一块儿的刷新问题必须保持一致性,推荐两篇文章,写得很好,对这个问题说得很清楚。

《Linux TLB 刷新的懒惰模式》

http://blog.csdn.net/Henzox/article/details/41963271

这篇文章主要讲述了在SMP处理器上,每个cpu有自己的tlb,在一个cpu借用某个用户进程的内存空间的时候,这个用户进程可能在另一个cpu上被调度执行,有可能引起这个进程内存空间的变化,tlb数据会失效,为了保持一致性,会向引用这个内存空间的cpu发送IPI消息通知其刷新对应的tlb条目。Task_struct中记录cpu对其mm_struct引用的信息存储在cpu_vm_mask中,最多支持32颗cpu信息记录,TLBSTATE_LAZY模式下,cpu处理IPI消息时,将该cpu对应位的掩码清除,不刷新tlb,下次IPI消息就不回发送到自己这里了。

《尝试总结memory barrier (经典)》

http://blog.csdn.net/zhangxinrun/article/details/5843632

这篇文章主要讲现代cpu在乱序执行以及编译优化,和JIT等技术使得cpu在真正执行指令的时候可能并不如同你写代码的时候的串行执行,加入内存壁障的作用就是防止gcc编译器对代码的优化,总的实现功能主要是保证内存壁障之前的写操作做完,内存壁障之后的读代码都从内存中重新读取数据。

内存壁障在x86上的实现方式是lock总线,这会使得所有cpu对lock涉及到的指令操作的数据的cache都失效,而lock会导致当前cpu将其cache写入内存,通过(BUS-Watching)技术,其他cpu会使有对应数据的cache失效,即下一次访问的时候必须从内存取。通过MESI协议,保持缓存一致性。

寄存器信息的切换源码

 1 #define switch_to(prev,next,last) do {                     2     asm volatile(
 3         "pushl %%esi\n\t"                     4         "pushl %%edi\n\t"                     5         "pushl %%ebp\n\t"                     6         "movl %%esp,%0\n\t"    /* save ESP */         7         "movl %3,%%esp\n\t"    /* restore ESP */     8         "movl $1f,%1\n\t"        /* save EIP */         9         "pushl %4\n\t"        /* restore EIP */    10         "jmp __switch_to\n"                11         "1:\t"                        12         "popl %%ebp\n\t"                    13         "popl %%edi\n\t"                    14         "popl %%esi\n\t"                    15         :"=m" (prev->thread.esp), "=m" (prev->thread.eip), 16         "=b" (last)                    17         :"m" (next->thread.esp), "m" (next->thread.eip), 18         "a" (prev), "d" (next), 19         "b" (prev));                    20 } while (0)

将esi,edi,ebp,esp存入task_struct中,并将1:开始处作为eip保存,下次找个进程被调度的时候,ret返回后就从这里开始执行。

加载新进程的esp,对eip压栈,这个eip实际上对应的就是上次自己被调度离开的时候存储的1:的位置,所以等最后ret返回的时候就从这里开始执行,恢复ebp,edi,esi,完全恢复进程。

__switch_to有FASTCALL标记,则这个函数的参数会在eax和edx中取,即对应prev和next。

__switch_to保存prev的fpu,fs,gs段,清空可能的io权限位图bitmap,将next进程的内核栈指针,fs,gs,可能的debug寄存器信息,并设置其io权限位图bitmap。

接下来就是内存管理了,还是挺快的。

时间: 2024-10-17 05:26:12

进程切换switch_to()注释的相关文章

进程切换switch_to宏第三个参数分析

进程切换一般都涉及三个进程,如进程a切换成进程b,b开始执行,但是当a恢复执行的时候往往是通过一个进程c,而不是进程b. 注意switch_to的调用: switch_to(prev,next,prev), 可以看到last就是prev 调用方法如下:进程A->进程B switch_to(A,B,A)主要有三个参数:输入参数两个:prev:切换前的进程 next:切换后的进程 输出参数一个:last:切换前进程  注意这三个变量都是局部变量,在系统栈中,所以切换到另一进程后变量的值不会改变.进程

lab8:理解进程调度时机跟踪分析进程调度与进程切换的过程

李俊锋 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.实验原理 1.操作系统的基本概念 任何计算机系统都包含一个基本的程序集合,称为操作系统. – 内核(进程管理,进程调度,进程间通讯机制,内存管理,中断异常处理,文件系统,I/O系统,网络部分) – 其他程序(例如函数库.shell程序.系统程序等等) 操作系统的目的 – 与硬件交互,管理所有的硬件资源 – 为用户程序(应

从整理上理解进程创建、可执行文件的加载和进程执行进程切换,重点理解分析fork、execve和进程切换

一.首先我们来看看进程控制块PCB也就是task_struct,(源码) 选出task_struct中几个关键的参数进行分析 struct task_struct {volatile long state; //进程状态 /* -1 unrunnable, 0 runnable, >0 stopped */ void *stack; //进程内核堆栈 atomic_t usage; unsigned int flags; //进程标识符 /* per process flags, defined

Linux内核设计第八周学习总结 理解进程调度时机跟踪分析进程调度与进程切换的过程

陈巧然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.视频内容 Linux系统的一般执行过程 最一般的情况:正在运行的用户态进程X切换到运行用户态进程Y的过程 1. 正在运行的用户态进程X 2. 发生中断——save cs:eip/esp/eflags(current) to kernel stack, then load cs:eip(entry of a specific IS

理解进程调度时机跟踪分析进程调度与进程切换的过程

李洋 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 这一次实验是针对linux系统中进程调度时机得深入理解. Linux 调度器将进程分为三类: 1. 交互式进程 2. 批处理进程 3. 实时进程 根据进程的不同分类 Linux 采用不同的调度策略.对于实时进程,采用 FIFO 或者 Round Robin 的调度策略.对于普通进程,则需要区分交互式和批处理式的不同.传统 Linux 

Linux内核源码学习之进程切换细节整理

linux中的进程是个最基本的概念,进程从运行队列到开始运行有两个开始的地方, 一个就是switch_to宏中的标号1:"1:/t",//只要不是新创建的进程,几乎都是从上面的那个标号1开始的,而switch_to宏则是除了内核本身,所有的进程要 想运行都要经过的地方 另 一个就是ret_form_fork 这样看来,虽然linux的进程体系以及进程调度非常复杂,但是总体看来就是一个沙漏状, 对于系统中的每个新进程它首次被执行的过程必然是: sys_fork---->do_for

实验八——理解进程调度时机跟踪分析进程调度与进程切换的过程

理解进程调度时机跟踪分析进程调度与进程切换的过程 攥写人:李鹏举  学号:20132201 ( *原创作品转载请注明出处*) ( 学习课程:<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000) 一.实验要求: 理解Linux系统中进程调度的时机,可以在内核代码中搜索schedule()函数,看都是哪里调用了schedule(),判断我们课程内容中的总结是否准确: 使用gdb跟踪分析一个schedule()函数 ,验

进程切换过程详解

/* 注:在学习内核的时候有一个困难,那就是任何一个模块都不是孤立的,比如进程的调度就设计到中断处理.信号处理还有进程上下文的切换等等.作为一个初学者,想一下子把操作系统的整个运行过程都清晰地展现在脑海是不现实的.尽管如此,每个模块还是有它所关注的焦点,我们所采取的策略是把整个操作系统分为几个大模块,比如:进程的管理.内存管理.文件系统等等.然后把这些大模块进一步分解成一个个小模块,比如进程的管理可以细分为进程的创建.进程的切换.系统调用的处理.信号的处理等等.在分析每一个模块时,先把其他的模块

详细分析contrex-A9的汇编代码__switch_to(进程切换)

//函数原型:版本linux-3.0.8 struct task_struct *__switch_to(structtask_struct *, struct thread_info *, struct thread_info *); #define switch_to(prev,next,last)                                       \ do {