(1)Asymptote——站在巨人的肩膀上编写一个属于自己的linux操作系统!

一. 前言

  最近无意间看到了一本书,《linux内核完全剖析》,竟然是零几年写的,真是深深佩服作者!这本书是基于早期的0.11版内核代码编写的,这也让我有了些许信心去阅读,如果去看2.6的代码,简直不敢想象。。。

       之前看过李述桐老师的《从零到一教你写嵌入式操作系统》的tinyOS,那个平台是stm32,当时在原子的开发板上面跟着视频编写并运行过,之后工作了每天都在接触linux,所以当看到《linux内核完全剖析》一书时,又激起了我的好奇心,也许我也可以?!!于是,便产生了这篇文章(一篇文章肯定不够,所以打算写一个系列,只要能坚持,代码还在写,记录就不会断),以此权当一个记录,因为我发现遇到的坑太多了,必须要记录一下。

二. 不罗嗦了,开始正题

    从18年12月27日开始写的,平台是之前学驱动时,买的韦东山老师的jz2440开发板。

    一开始,先从多任务开始。这里遇到的坑就开始很多了,《linux内核完全剖析》书中的0.11内核源码,当时Linus Torvalds是基于x86架构芯片写的,而现在的板子是arm架构,所以里面的涉及到汇编代码的内容基本不可以借鉴。。。于是我首先想到了之前的stm32下的tinyOS,里面的关于多任务qie'切换的代码可以借鉴,但是后来仔细阅读发现,他利用的是M3核的pendsvc异常来实现任务切换的,但是arm9的jz2440没有这个异常模式,依靠自己感觉太难了,基本没什么思路,所以又从网上开始找,幸运的是找到了——https://blog.csdn.net/jgw2008/article/category/6215030,姜广伟大神写于10年的几篇文章(再次深深佩服)。

     一开始我有个疑问,就是任务切换之后一定要进入异常模式吗?答案是否定的。

     我在姜大神的文章基础上进行了一些改动,下面叙述一下实现的过程:

(1)Asymptote——站在巨人的肩膀上编写一个属于自己的linux操作系统!_第1张图片

     如上图所示,首先需要明确几个变量:

1. (unsigned long *)TaskCur_STK_PTR

       存放当前执行的任务的地址

2. (unsigned long *)TaskNext_STK_PTR

       存放下一个执行的任务的地址

3. (unsigned long *)Task01_STK_PTR

       存放第一个任务中的栈sp地址

4. (unsigned long *)Task02_STK_PTR

       存放第二个任务中的栈sp地址

之后依次类推。。。

之所以要设置这几个变量,因为栈指针sp在入栈、出栈过程中是一直在变的,当前和下一个任务也是一直在变的,所以分别需要变量去保存。

下面是切换任务的汇编代码:

switch_to:
	@ 将“当前任务”寄存器值压栈。
	stmfd sp!,{lr}              @ PC 入栈
	stmfd sp!,{r0-r12,lr}		@ r0-r12,lr入栈			
	mrs r4,cpsr
	stmfd sp!,{r4}				@ cpsr入栈

	@ 保存“当前任务”的栈顶指针。
	ldr r5,=TaskCur_STK_PTR		@ 取出存放“当前任务”的堆栈指针的地址
	ldr r5, [r5]
	str sp,[r5]                 @ 保存“当前任务”的堆栈指针			

	@ 计算存放“当前任务”堆栈指针的地址。
	ldr r0, =TaskCur_STK_PTR	
	ldr r1, =TaskNext_STK_PTR
	ldr r1, [r1]				 
	str	r1, [r0]		

	@ 取出“下一个任务”的栈顶指针,并将寄存器依次出栈。
	ldr r6, =TaskNext_STK_PTR	@ 取出存放"下一个任务"的Stack Pointer的地址
	ldr r6, [r6]
	ldr sp, [r6]				@ 取出"下一个任务"的堆顶指针,赋给SP         		
	ldmfd sp!,{r4}              @ cpsr出栈
	msr CPSR_cxsf,r4	
	ldmfd sp!,{r0-r12,lr,pc}    @ r0-r12,lr,pc出栈		

之后将要运行的任务的起始地址赋给pc,就可以实现任务切换了。

 

 

 

 

 

 

你可能感兴趣的:(操作系统)