为了任务能够交替执行。所以才有了进程的概念。
进程是怎样让任务交替执行的?
进程是什么 执行序列和资源+现场环境
启动磁盘读写 // 设置当前进程状态为阻塞态 pCur.state='W' 将pCur放到DiskWaitQueue schedule() // 一 :schedule 函数 schedule(){ // 从就绪队列中选出下一个准备运行的进程 pNew=getNext(ReadyQueud); // 切换到下一个进程 switch_to(pCur,pNew) } // 二:switch_to函数 switch_to(pCur,pNew){ // 保存上一个进程的执行进度 pCur.ax = CPU.ax; pCur.bx = CPU.bx; ... // 代码段基地址 pCur.cs = CPU.cs; // pc: 指向下一条待执行的指令 pCur.retpc = CPU.pc; // 恢复待执行进程的执行进度 CPU.ax = pNew.ax; CPU.bx = pNew.bx; ... CPU.cs = pNew.cs; CPU.retpc = pNew.pc; }
void Yield(){ TCB1.esp=esp; esp=TCB2.esp; }
内核线程创建和撤销都是操作系统干的事 所以操作系统可感知到线程的存在 ,可以利用多核的优势
内核态线程,创建成本高 通常我们会在内核中预先创建一些线程,并反复利用这些线程
main() { A(); B(); } A(); { //fork是系统调用,引会引起中断 // fork 不仅可以引起切换 也可以引起切换 fork(); }
_system_call: // 各种压栈 注意是压的是用户寄存器的值 push %ds..%fs pushl %edx... call sys_fork pushl %eax movl _current,%eax // 判断当前线程是否阻塞 cmpl $0,state(%eax) // 切换 jne reschedule // 判断当前线程是否时间片用完 cmpl $0,counter(%eax) // 切换 je reschedule ret_from_sys_call:
// 进程切换函数 void schedule(void){ // 根据调度算法选择一个合适的线程 next=i; // 切换到下个进程 switch_to(next); }
// 系统调用返回 ret_from_sys_call: popl %eax // 回值popl %ebx ... pop %fs ... iret// 返回到int 0x80后面执行 mov res,%eax res=?
int copy_process(int nr,long ebp,long edi,long esi,long gs,long none,long ebx,long ecx,long edx, long fs,long es,long ds,long eip,long cs,long eflags,long esp,long ss) copy_process: // 申请TCB p=(struct task_struct *)get_free_page(); //创建内核栈 p->tss.esp0 = PAGE_SIZE + (long) p; p->tss.ss0 = 0x10; // 创建用户栈(和父进程共用的用户栈) p->tss.ss = ss & 0xffff; p->tss.esp = esp;
时间片+动态调整优先级算法
作用counter:优先级 和 时间片
void Schedule(void) //在kernel/sched.c中 { while(1) { c=-1; next=0; i=NR_TASKS; // NR_TASKS 队列的length p=&task[NR_TASKS]; while(--i){ // 1.从就绪队列中找出最大的counter运行 if((*p->state == TASK_RUNNING && (*p)->counter>c) c=(*p)->counter, next=i; } if(c) break; //找到了最大的counter // 动态调整优先级所有任务的的优先级 优先级=1/2*counter + priority(时间片) // 如果任务被调度过那么 counter=0 即 优先级=1/2*0 + priority(时间片) 所有动态调整后 没运行的优先级会被调高 for(p=&LAST_TASK;p>&FIRST_TASK;--p) (*p)->counter=((*p)->counter>>1) +(*p)->priority; } // 切换到下一个进程运行 switch_to(next);}
struct semaphore { int value;// 记录资源的个数 PCB *queue; //记录等待在该信号量上的进程 } p(semaphore s) // 消费资源 v(semaphore s) // 生产资源 P(semaphore s){ s.value--; if(s.value<0){ sleep(s.quenue); } } V(semaphore s){ s.value++; if(s.value<=0){ wakeup(s.quenue); } }
互斥进入
有空让进
有限等待