📄 00000002.htm
字号:
1.将栈顶寄存器压入堆栈. <BR> 2.调用 StartupPC 函数. <BR> 3.调用 InitialPC 函数. <BR> 4.调用 WhenDonePC 函数. <BR> 5.恢复栈顶寄存器. <BR> 事实上执行 WhenDonePC函数过程中,此进程就放弃了处理机,由其他进程将它所占 <BR>的内存空间释放,此进程将不再运行.从ThreadRoot函数的执行过程可以看出它才是进 <BR>程运行的全过程. <BR> 正文切换中用到的另一个函数是SWITCH(Thread* oldThread,Thread*newThread), <BR>oldThread指向正在运行的进程对象,newThread指向将要运行的进程对象,在Thread对 <BR>象中有一块内存用来放本进程的CPU寄存器的内容,SWITCH函数先将宿主机的CPU寄存器 <BR>的内容保存到oldThread对象中,再从newThread对象中恢复除指令寄存器(PC)以外的所 <BR>有寄存器的内容,由于栈基址和栈顶寄存器的内容变为新进程的值,所以程序将在新进 <BR>程的堆栈上运行,当SWITCH函数结束返回时,会从新进程的堆栈中取出返回地址,这个地 <BR>址是新进程的断点而不是老进程的断点,所以CPU将执行新进程的代码,由此实现新老进 <BR>程的正文切换.因为SWITCH需要存取CPU寄存器,并且与具体机器有关,所以它用汇编语 <BR>言写成. <BR> Scheduler类用于实现进程的调度.它的类界面如图所示: <BR> <BR> ┏━━━━━━━━━━━┓ <BR> ┃ Scheduler ┃ <BR> ┣━━━━━━━━━━━┫ <BR> ┃ ReadyToRun ┃ <BR> ┃ FindNextToRun ┃ <BR> ┃ Run ┃ <BR> ┗━━━━━━━━━━━┛ <BR> <BR> Schedule类维护一个就绪进程队列,当一个进程可以占用处理机时,就可以调用 <BR>ReadyToRun成员函数把这个进程放入就绪进程队列,并把进程状态改成就绪态. <BR> FindNextToRun函数根据调度策略,取出下一个应运行的进程,并把这个进程从就绪 <BR>进程队列中删除.如果就绪进程队列为空,则此函数返回空(NULL).现有的调度策略是先 <BR>进先出策略(FIFO),在课程中将要求学生们实现其他的调度策略. <BR> Run函数用来调用另一个进程占用CPU.它的实现过程是: <BR> 1.如果当前进程(由currentThread指明)是用户进程, <BR> 则保存用户程序状态和用户空间的状态. <BR> 2.将新进程的地址赋给currentThread变量,表明当前进程变为新进程了. <BR> 3.将新进程的状态改为运行态. <BR> 4.调用SWITCH函数切换进程正文. <BR> 5.查看有没有已经结束但没有删除的进程,如果有,则将其删除. <BR> 6.如果新进程是用户进程,则恢复用户程序状态和用户空间的状态. <BR> 当老进程是因为结束而放弃CPU,我们要把它所占的内存释放,那么在什么时候删除 <BR>它呢?这里有个时机问题.我们只能在第五步上删除,在此之前是不行的.因为在此之前, <BR>程序还运行在老进程的堆栈上,如果过早删除老进程,它的堆栈也被删掉了.造成内存出 <BR>错. <BR> Thread类的对象既用作进程的控制块,保存进程状态和CPU寄存器内容,又是用户调 <BR>用进程系统的界面. <BR> 用户生成一个新进程的方法是: <BR> <BR> /* 生成一个进程类*/ <BR> Thread* newThread = new Thread("New Thread"); <BR> /*定义新进程的执行函数及其参数*/ <BR> newThread->Fork(ThreadFunc,ThreadFuncArg); <BR> <BR> <BR> Fork函数分配一块固定大小的内存作为进程的堆栈,在栈顶放入ThreadRoot的地 <BR>址.当新进程被调上CPU时,要用SWITCH函数切换进程图像,SWITCH函数返回时,会从栈 <BR>顶取出返回地址,所以将ThreadRoot放在栈顶,SWITCH结束后就会执行ThreadRoot函数 <BR>了. <BR> ThreadRoot函数在前面已作了介绍,它是进程完整的执行过程.它的InitialPC及 <BR>InitialArg参数传的是Fork的两个参数;StartupPC参数传的是一个开中断函数,它将 <BR>在进程首次占用处理机时立即执行;WhenDonePC参数传的是Thread类的Finish成员函 <BR>数,它将在进程的工作函数执行完毕后运行,作一些收尾工作.它的执行过程是: <BR> 1.关闭中断. <BR> 2.将当前进程赋给全局变量threadToBeDestroyed, <BR> 以便在它让出CPU后,在SWITCH函数中将它删除. <BR> 3.调用Sleep函数睡眠等待.实际上进程在睡眠等待的时候就被删除了, <BR> 所以它不会从Sleep函数中返回的. <BR> <BR> Yield函数用于本进程放弃处理机.它的执行过程是: <BR> <BR> ┏━━━━━━━━┓ <BR> ┃ 关闭中断并记住 ┃ <BR> ┃ 原来的中断状态 ┃ <BR> ┗━━━┳━━━━┛ <BR> ┃ <BR> ↓ <BR> ━━━━━━━━━ Y <BR> 进程就绪队列 ━━━┓ <BR> 为空? ┃ <BR> ━━━━━━━━━ ┃ <BR> ┃ ┃ <BR> ┃N ┃ <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -