⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sched.c

📁 一个基于MMU的操作系统的实现(代码很少
💻 C
字号:
#include <sched.h>#include <s3c2410.h>#include <interrupt.h>#include <init.h>#include <mmu.h>#include <string.h>#include <serial.h>struct task_struct task[TASK_NR];struct task_struct*  current = NULL;extern void __switch_to(struct task_struct *pcur,struct task_struct *pnext);/****************************************************************************** 初始化task数组* 初始化任务0,即task[0]*****************************************************************************/void sched_init(void){	struct task_struct *p = &task[0];	int i,j;	DPRINTK(KERNEL_DEBUG,"\n\rkernel:sched_init,create task 0\n\r");		for(i = 0; i < TASK_NR; i++,p++){		p->pid = -1;		p->state = TASK_UNALLOCATE;		p->count = 0;		p->priority = 0;		for(j = 0; j < 1024; j++){			p->kernelstack[j] = 0;		}	}	p = &task[0];	p->pid = 0;	p->state = TASK_RUNNING;	p->count = 5;	p->priority = 5;	p->content[0] = (unsigned long)(&task[1]);	p->content[1] = 0x5f;   		/*cpsr*/	p->content[2] = 0x30100000-1024;	/*usr/sys模式堆栈*/	p->content[3] = 0x13;		/*svc模式*/	p->content[17]= 0;		/*pc*/		current = &task[0];}/****************************************************************************** 切换到task数组中处于运行状态的、count值最大的任务* 如果所有任务的count值都为0,则重新计算count = count / 2 + priority* 进程0不参与竞争*****************************************************************************/void schedule(void){	long max = -1;	long i = 0,  next = 0;	struct task_struct * ptmp_tsk = NULL;	DPRINTK(KERNEL_DEBUG,"kernel:schedule\n\r");		while(1){		for(i = 1; i < TASK_NR; i++){			if((task[i].state == TASK_RUNNING)&&(max < (long)task[i].count)){				max = (long)task[i].count;				next = i;			}		}		/*如果所有任务都不处于就绪状态,max = -1,next = 0,跳出循环执行任务0*/		/*如果max = 0,则进行下面的计算count值*/		/*如果max > 0,则跳出循环...*/		/*这种方法太妙了,摘自linux0.11*/		if(max)break;			for(i = 0; i < TASK_NR; i++){			task[i].count = (task[i].count >> 1) + task[i].priority;		}	}	if(current == &task[next])		return;	if(task[next].pid < 0)		return;	ptmp_tsk = current;	current = &task[next];	DPRINTK(KERNEL_DEBUG,"kernel:__switch_to\n\r");			__switch_to(ptmp_tsk,&task[next]);	DPRINTK(KERNEL_DEBUG,"kernel:return from __switch_to\n\r");			}/****************************************************************************** 当前进程count减1* 如果当前进程不处于可运行状态,或count=0,调度进程*****************************************************************************/void do_timer(void){	int i = 0, b_wakeup = 0;	DPRINTK(KERNEL_DEBUG,"kernel:do_timer\n\r");			for(i = 1; i < TASK_NR; i++){		if(task[i].state == TASK_SLEEPING){			if(!(--task[i].timer)){				task[i].state = TASK_RUNNING;				b_wakeup = 1;			}		}	}	if(current->count){		current->count--;	}		if((current->state != TASK_RUNNING)|| !current->count || b_wakeup){		schedule();	}	DPRINTK(KERNEL_DEBUG,"kernel:leaving do_timer\n\r");			}/******************************************************************************** linux下,在控制台下如此运行程序:file  param0 param1 ...* 其中的file  param0 param1 ...作为参数传递给int main(int argc, char **argc)* argc为参数个数,即file,param0,param1...的个数* argv[0]为file字串的地址,argv[1]为param0字串的地址...** OSCreateProcess中参数含义为:* 1. nand_start_addr:本进程代码存在nand flash中的位置,len:代码大小,通过这两个参数来* 确定一个文件file* 2. parameters为"param0 param1 param2 ...",各参数间以空格分开* 请注意,进程main函数中的file参数就没什么用处了,我随便设为pid了* 3. priority:进程优先级** 本函数用于从nand flash中读处代码,设置其main函数执行前的环境:堆栈、参数,设置相应的任务数据结构**********************************************************************************/int OSCreateProcess(unsigned long nand_start_addr, unsigned long len, char *parameters, long priority){	unsigned long i = 1,pid,j,argc = 0;	unsigned long *p_VA;	char *pDes;		DPRINTK(KERNEL_DEBUG,"kernel:OSCreateProcess\n\r");		for(; i < TASK_NR; i++){		if(!(task[i].state == TASK_UNALLOCATE && VALIDE_TASK_INDEX(i)))			continue;				OS_ENTER_CRITICAL();		pid = i;		/*从NAND Flash中复制代码到进程号i对应的物理地址*/		/*虚拟地址SDRAM_RAW_RW_VA_BASE + i*0x100000指向PID=i的进程的1M内存,并且此虚拟地址>32M,所以与PID无关*/		DPRINTK(KERNEL_DEBUG,"kernel:OSCreateProcess::nand_read_ll\n\r");		p_VA = (unsigned long *)(SDRAM_RAW_RW_VA_BASE + pid*0x100000);								//清0		for( j = 0; j < 0x100000/4; j++)			p_VA[j] = 0;				nand_read_ll((unsigned char*)p_VA, nand_start_addr,len);		/****************************************************************************************		* 设置用户函数int main(int argc, char **argc)的参数		* 进程i的1M地址的最后1k空间用于存放参数(地址向上依次为):		* argc,argv[0],argv[1],...,argv[argc-1],NULL,"argv[0]对应的string","argv[1]对应的string",...		*****************************************************************************************/		DPRINTK(KERNEL_DEBUG,"kernel:OSCreateProcess::set the new process's parameters\n\r");					//放参数		p_VA = (unsigned long *)(SDRAM_RAW_RW_VA_BASE + pid*0x100000 + 0x100000 - 1024);				argc = 0;		j = 0;		/*计算paramters中参数个数*/		if(parameters){			while(parameters[j]){				while(parameters[j] == ' ')j++;	//吃掉空格				if(!parameters[j])					break;				argc++;				while(parameters[j] && ( parameters[j] != ' '))j++;	//吃掉非空格				if(!parameters[j])					break;			}		}						*p_VA++ = argc + 1;	   	/*main函数中的argc*/				*p_VA++ = pid;		/*argv[0]*/		pDes = (char *)(p_VA + argc + 1);	/*pDes指向"...,argc[argc-1],NULL"后面,用来存放argv[...]对应的字符串*/		for(i = 0, j = 0; i < argc; i++){			*p_VA++ = (unsigned long)pDes -(SDRAM_RAW_RW_VA_BASE + pid*0x100000);			while(parameters[j] == ' ')j++;	//吃掉空格						if(!parameters[j])				break;			while(parameters[j] && ( parameters[j] != ' ')){//复制参数 				*pDes = parameters[j];				pDes++;				j++;			}			*pDes = '\0';					       	pDes = (char *)(((unsigned long)pDes + 4)&(~0x3)); 	//对齐			if(!parameters[j])				break;		}						/************************************************************************************		* 设置参数:		* 进程刚开始处于usr/sys模式		* 参考sched.S中保存进程上下文的顺序为:		* sp_svc,cpsr,sp_usr/sys,0x13(表示svc),r0-r12,lr		**************************************************************************************/		DPRINTK(KERNEL_DEBUG,"kernel:OSCreateProcess::set the new process's content\n\r");		task[pid].pid = pid;		task[pid].state = TASK_RUNNING;		task[pid].count = 15;		task[pid].priority = priority;		task[pid].content[0] = (unsigned long)(&task[pid+1]);		task[pid].content[1] = 0x5f;   	/*cpsr*/		task[pid].content[2] = 0x100000-1024; /*usr/sys模式堆栈*/		task[pid].content[3] = 0x13;	/*svc模式*/		task[pid].content[17]= 0;	/*pc*/				OS_EXIT_CRITICAL();		return 1;	}		return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -