任务结构数组(或链表)的实现
我们的任务结构就采用链表形式吧,但其长度是限定了的,头指针是一个全局指针变量( 指针变量是一个无符号整型指针,其指针本身所在的地址是在BSS段,但其指向的内容是分 配在堆上的一片内存),分配内核内存的函数就用kmalloc吧,kmalloc函数需要自己编写 呵,为了简单,这个函数只接受一个参数,就是所需分配大小,这个函数做得很简单,首先 有一个全局针指,它在初始化时指向了整个堆的起始位置,并且固定大小,就是所谓的内核 堆栈,在内核堆栈之后就是用户堆栈,由于总共有十个任务,当然不包括内核本身的任务, 所以整个堆栈就平均分成十一部分,注意:在所有任务初始化完成之后,还有一个步骤就是 将内核这个任务移到用户态,相当于要将自己的任务结构的堆栈指针修改一下就行了), 判断大小是否超出了内核堆的可分配范围,还有一点,需要维护内核堆和其它任务的堆, 需要进行分块,并且有一个全局的内存使用标识,就用数组吧,简单,0表示相应的内存 部分未占用,1就表示占用,对应的kfree就相当于把标志置0), 对于内存的维护,比较复杂,为了简单,就定为4K,并且不能进行大于四K的内存申请,因为 大于4K之后,由于没有虚拟地址的概念,就不能实现堆上的连续分配地址,当然在栈上分配 是可以大于4K的,栈是由编译器和CPU所决定了的
任务结构包括: 1.所剩的时间片 2.本任务所指向的代码段内存地址,这里也就是函数入口地址 3.本任务所指向的数据段地址,这里的数据段被包含进了整个内核中,所以并没有用,作为保留 4.本任务的函数体是否存在,也就是否会被调度 5.本任务所使用的栈指针 6.本任务所使用的堆指针 7.本任务的标识,用0代表是IDLE,1代表是其它进程 8.所有寄存器的值 9.当前PC值,初始化时被置成了函数入口地址
首先讲解一下任务数组结构的初始化: 将先定义一个全局指针,然后将此指针强制转换为一个任务结构指针,并通过kmalloc函在内核所占用的堆(前而讲过内核的堆的起始就是整个堆的起始)上去分配十个任务结构所占的内存,这里是绝不会超过4K的并且为这十个任务结构赋值,将第一个任务置为IDLE,时间片为20,代码段内存地址为main函数的的地址,数据段地址忽略,函数体存在,可以被调度,栈指针指向的位置根据以下来计算:
假定每个给每个任务可使用的堆栈设定为64K,而整个堆的起始位置是0x20030000,那么第一个堆指针所指向的就是0x20030000,栈就是0x20030000+64K的位置,第二个以后就以此类推注意:在初始化任务结构之前,不允许系统使用堆,但可以使用栈,那么内核任务栈部分就分成了两个,在未进行调度之前,栈就是上一页中第二步中所设的栈,那么上一页设置堆栈的时候就得注 意必须将堆栈空间设成十个64K再加上在本步骤使用以前的最大可能所需的栈空间
|