欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

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

程序员文章站 2022-03-11 20:43:59
一. 前言 最近无意间看到了一本书,《linux内核完全剖析》,竟然是零几年写的,真是深深佩服作者!这本书是基于早期的0.11版内核代码编写的,这也让我有了些许信心去阅读,如果去看2.6的代码,简直不敢想象。。。 之前看过李述桐老师的《从零到一教你写嵌入式操作系统》的tinyOS,那个平台是stm32,当时在原子的开发板上面跟着视频编写并运行过,之后工作了每天都在接触linu......

一. 前言

  最近无意间看到了一本书,《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. (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,就可以实现任务切换了。

 

 

 

 

 

 

本文地址:https://blog.csdn.net/CallMe_Xu/article/details/85940082

相关标签: 操作系统