进程0要做的第一件事就是作为父进程调用fork函数创建第一个子进程——进程1。
内核用last_pid来存放系统自开机以来累计的进程数,也将此变量用作新建进程的进程号。BTW,linux 0.11 的task[64]只有64项,最多只能同时运行64个进程。fork函数中有个很重要的函数叫 copy_process() 函数。
进程0依靠它完成对进程1的创建:
1) 为进程1创建task_struct,将进程0的task_struct的内容复制给进程1
2) 为进程1的task_struct、tss做个性化设置
3) 为进程1创建第一个页表,将进程0的页表项内容赋给这个页表
4) 进程1共享进程0的文件
5) 设置进程1的GDT项
6) 最后将进程1设置为就绪状态,使其可以参与进程间的轮转。
在copy_process内部还有一个重要的函数 get_free_page(),它在主内存申请一个空闲页面,并将申请到的页面清零,用于进程1的task_struct及内核栈。
完成进程1的task_struct设置后,接下来——
设置进程1的分页管理。每个进程都要加载属于自己的代码、数据。这些代码、数据的寻址都是用段加偏移的形式,也就是逻辑地址形式表示的。CPU硬件自动将逻辑地址计算为CPU可寻址的线性地址,再根据操作系统对页目录表、页表的设置,自动将线性地址转换为分页的物理地址。
线性地址(32位)= 页目录项(10位)+ 页表项(10位)+ 页内偏移 (12位)
CR3是页目录基址寄存器,保存页目录表的物理地址,页目录表总是放在以4K字节为单位的存储器边界上,因此,它的地址的低12位总为0,不起作用,即使写上内容,也不会被理会。
时间: 2024-10-06 00:41:31