进程调度


任务调度主要是协调任务对计算机系统内资源(如内存、i/o设备、cpu)的争夺


使用。进程调度又称为cpu调度,其根本任务是按照某种原则为处于就绪状态


的进程分配cpu。由于嵌入式系统中内存和i/o设备一般都和cpu同时归属于


某进程,所以任务调度和进程调度概念相近,很多场合不加区分,下文中提到的


任务其实就是进程的概念。


进程调度可分为"剥夺型调度"和"非剥夺型调度"两种基本方式。所谓"非剥夺型


调度"是指:一旦某个进程被调度执行,则该进程一直执行下去直至该进程结束,


或由于某种原因自行放弃cpu进入等待状态,才将cpu重新分配给其他进程。


所谓"剥夺型调度"是指:一旦就绪状态中出现优先权更高的进程,或者运行的进


程已用满了规定的时间片时,便立即剥夺当前进程的运行(将其放回就绪状态),


把cpu分配给其他进程。


作为实时操作系统,uc/os是采用的可剥夺型实时多任务内核。可剥夺型的实时


内核在任何时候都运行就绪了的最高优先级的任务。uc/os中最多可以支持64


个任务,分别对应优先级0~63,其中0为最高优先级。调度工作的内容可以分


为两部分:最高优先级任务的寻找和任务切换。


其最高优先级任务的寻找是通过建立就绪任务表来实现的。uc/os中的每一个任


务都有独立的堆栈空间,并有一个称为任务控制块tcb(task control block)数据


结构,其中第一个成员变量就是保存的任务堆栈指针。任务调度模块首先用变量


ostcbhighrdy记录当前最高级就绪任务的tcb地址,然后调用os_task_sw()


函数来进行任务切换。


uclinux的进程调度沿用了linux的传统,系统每隔一定时间挂起进程,同时系


统产生快速和周期性的时钟计时中断,并通过调度函数(定时器处理函数)决定进


程什么时候拥有它的时间片。然后进行相关进程切换,这是通过父进程调用fork


函数生成子进程来实现的。


uclinux系统fork调用完成后,要么子进程代替父进程执行(此时父进程已经


sleep),直到子进程调用exit退出;要么调用exec执行一个新的进程,这个时候


产生可执行文件的加载,即使这个进程只是父进程的拷贝,这个过程也不可避免。


当子进程执行exit或exec后,子进程使用wakeup把父进程唤醒,使父进程继续


往下执行。


uclinux由于没有mmu管理存储器,其对内存的访问是直接的,所有程序中访


问的地址都是实际的物理地址。操作系统队内存空间没有保护,各个进程实际上


共享一个运行空间。这就需要实现多进程时进行数据保护,也导致了用户程序使


用的空间可能占用到系统内核空间,这些问题在编程时都需要多加注意,否则容


易导致系统崩溃。


由上述分析可以得知,uc/os内核是针对实时系统的要求设计实现的,相对简单,


可以满足较高的实时性要求。而uclinux则在结构上继承了标准linux的多任务


实现方式,仅针对嵌入式处理器特点进行改良。其要实现实时性效果则需要使系


统在实时内核的控制下运行,rt-linux就是可以实现这一个功能的一种实时内


核。