八、用户进程:TSS、用户进程的创建、用户进程的执行(通过调度函数)

TSS

起初Intel的建议是给每个任务都关联一个任务状态段(TSS)。在CPU中有一个TR寄存器,始终指向当前正在运行的任务,因此在CPU看来,任务切换的实质就是TR寄存器指向不同的TSS。但是Linux中,所有的任务共享一个TSS。TSS和其他段一样,本质上也是一片储存数据的区域,CPU用这片区域保持任务的最新状态。因此,TSS段就要像其他段一样,需要用个描述符来描述TSS段。因此也要在GDT中注册好。注意的是,TSS是属于系统段描述符,因此 S 为0。TSS描述符用来描述TSS段,TSS段在内存中,它的元素按照固定格式来排列。
TSS段里面基本上全部都是寄存器的名字,这些寄存器就是任务运行中的最新状态。TSS中有三组栈,Linux只使用了SS0和esp0。当任务被换下CPU时候,CPU自动的将当前任务的资源状态保存到该任务对应的TSS中,CPU通过新任务的TSS选择子加载新任务时候,会将新任务的TSS中的数据加到寄存器中,同时更新TR,使其指向新任务的TSS,当然我们的Linux不需要这样,因为只使用一个TSS。TSS段也需要选择子来访问的。TR寄存器保存的是TSS的选择子,任务改变就更新TR寄存器中的选择子可以指向另一个TSS了。
注意分清:TSS只是一个内存段的名字而已,它和数据段,代码段一样的,都需要一个描述符来描述这个段的属性和位置。GDT中储存着这些描述符,GDTR储存着段描述符表的位置,TSS的描述符只是GDT中的一个描述符而已。TR中储存的是TSS的选择子。任务切换就是改变TR的指向。

现代操作系统采用的任务切换

CPU由低特权级向更高特权级转移的一种情况是用户模式下面发生中断,这会发生堆栈的切换。Linux中只用到一个TSS,所以我们必须提前创建一个TSS,并且至少初始化TSS中的 ss0 和 esp0。因此我们使用TSS的唯一理由就是为0特权级的任务提供栈。当用户模式下发生中断时候,CPU会自动的从TSS 中取出 0 级栈,然后一系列 push 指令。

实现用户进程

进程与内核线程最大的区别就是进程有单独的4GB空间。每一个进程都有4GB的空间,也就是说每个进程都有一个页表。进程是基于线程实现的,它与线程一样使用相同的pcb结构,即 struct task_struct。我们在进程的PCB结构中加入两个成员:
uint32_t* pgdir;	//进程自己页表的虚拟地址
struct virtual_addr userprog_vaddr;	//用户进程的虚拟地址池
页表使用虚拟地址是因为页目录表本身也要占用内存来存储,我们在为进程创建页目录表,肯定要为页目录表申请内存,内存管理系统返回的地址肯定都是虚拟地址,不可能返回物理地址。

为进程创建页表和3特权级栈

不同的进程有各自不同的页表,因为我们创建一个进程就要为进程单独创建一个属于它的页目录表+页表。另外还要为用户进程创建在3特权级下面的栈。
//功能:在虚拟地址池中申请 n 页的页表,并返回起始地址
//需要注意到是:内核的虚拟地址池是全局变量,但是用户进程的虚拟地址池是在用户进程PCB中的,即一个用户进程有个属于它自己的虚拟地址池。
static void* vaddr_get(enum pool_flags pf, uint32_t pg_cnt) {
   int vaddr_start = 0, bit_idx_start = -1;
   uint32_t cnt = 0;
   if (pf == PF_KERNEL) {     // 内核内存池
      bit_idx_start  = bitmap_scan(&kernel_vaddr.vaddr_bitmap, pg_cnt);
      if (bit_idx_start == -1) {
	 return NULL;
      }
      while(cnt < pg_cnt) {
	 bitmap_set(&kernel_vaddr.vaddr_bitmap, bit_idx_start + cnt++, 1);
      }
      vaddr_start = kernel_vaddr.vaddr_start + bit_idx_start * PG_SIZE;
   } else {	     // 用户内存池	
      struct task_struct* cur = runnin
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值