remark: Autumn Wind + original works reproduced please specify the source + "Linux kernel analysis" MOOC course http://mooc.study.163.com/course/USTC-1000029000
1. After configuring the environment, start the kernel with the QEMU emulator and run the following:
650) this.width=650; "src=" Http://s3.51cto.com/wyfs02/M01/5B/47/wKioL1UFP0Tj3LtcAAMY50auwu8291.jpg "title=" Qq20150314094250.png "alt=" Wkiol1ufp0tj3ltcaamy50auwu8291.jpg "/>
650) this.width=650; "src=" http://s3.51cto.com/wyfs02/M00/5B/4D/wKiom1UFPgbi_ByoAAIc3oq_5lo273.jpg "style=" float: none; "title=" Qq20150314094811.png "alt=" Wkiom1ufpgbi_byoaaic3oq_5lo273.jpg "/>
2. Realize the source code of time slice rotation multi-Channel program Dispatch:
Mymain.c
/* * linux/mykernel/mymain.c * * kernel internal my_start_ kernel * * copyright (C) 2013 mengning * */#include <linux/types.h> #include <linux/string.h> #include <linux/ctype.h> #include < linux/tty.h> #include <linux/vmalloc.h> #include "Mypcb.h" TPCB&NBSP;TASK[MAX_TASK_NUM];TPCB * my_current_task = null;volatile int my_need_sched = 0;void my_ Process (void); Void __init my_start_kernel (void) { int pid = 0; int i; /* Initialize process 0*/ task[pid].pid = pid; task[pid].state = 0;/* -1 unrunnable, 0 runnable, >0 stopped */ task[pid]. Task_entry = task[pid].thread.ip = (Unsigned long) my_process; task[pid].thread.sp = (Unsigned long) &task[pid].stack[kernel_stack_size-1]; task[pid].next = &task[pid]; /*fork more process */ for (i=1;i<max_task_num;i++) { memcpy (&task[i],&task[0],sizeof (TPCB)); task[i].pid = i; task[i].state = -1; task[i].thread.sp = (Unsigned long) &task[i].stack[kernel_ stack_size-1]; task[i].next = task[i-1].next; task[i-1].next = &task[i]; } /* start process 0 by task[0] */ pid = 0; my_current_task = &task[pid];asm volatile ( "movl %1 ,%%esp\n\t " /* set task[pid].thread.sp to esp */ " PUSHL %1\n\t " /* push ebp */ "pushl %0\n\t" /* push task[ pid].thread.ip */ "ret\n\t" /* pop task[pid].thread.ip to eip */ " Popl %%ebp\n\t " : : " C " (Task[pid]. THREAD.IP), "D" (TASK[PID].THREAD.SP)/* input c or d mean %ecx/%edx*/);} void my_Process (void) { int i = 0; while (1) { i++; if (i%10000000 == 0) { &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;PRINTK (kern_notice "this is process %d -\n ", my_current_task->pid); if (my_need_sched == 1) { my_need_sched = 0; my_schedule (); &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;}&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;PRINTK (KERN_NOTICE " This is process&nBsp;%d +\n ", My_current_task->pid); } }}
mybcp.h
/* * linux/mykernel/mypcb.h * * kernel internal pcb types * * Copyright (C) 2013 mengning * */#define max_task _num 4#define kernel_stack_size 1024*8/* CPU-specific state of this task */struct Thread { unsigned longip; unsigned longsp;}; Typedef struct pcb{ int pid; volatile long state;/* -1 unrunnable, 0 runnable, >0 stopped */ char stack[kernel_stack_size]; /* cpu-specific state of this task */ struct Thread thread; unsigned longtask_entry; struct  Pcb *next;} Tpcb;void my_schedule (void);
myinterrupt.c
/* * linux/mykernel/myinterrupt.c * * kernel internal my_timer_ handler * * copyright (C) 2013 mengning * */#include <linux/types.h> #include <linux/string.h> #include <linux/ctype.h> #include < linux/tty.h> #include <linux/vmalloc.h> #include "Mypcb.h" Extern tpcb task[max_task _num];extern tpcb * my_current_task;extern volatile int my_need_sched;volatile int time_count = 0;/* * Called by timer interrupt. * It runs in the name of current running process, * so it use kernel stack of current running process */void my_timer_ Handler (void) {#if 1 if (time_count%100 == 0 && my_need_ Sched != 1) &NBSP;&NBSP;&NBSP;&NBSP;{&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;PRINTK (KERN_NOTICE ">> >my_timer_handler here<<<\n "); my_need_sched = 1; } time_count ++ ; # Endif return; }void my_schedule (void) {&NBSP;&NBSP;&NBSP;&NBSP;TPCB * next; tpcb * prev; if (My_current_task == null | | my_current_task->next == null) { return; &NBSP;&NBSP;&NBSP;&NBSP;}&NBSP;&NBSP;&NBSP;&NBSP;PRINTK (kern_notice ">>>my_schedule<<<\ n "); /* schedule */ next = my_current_task- >next; prev = my_current_task; if (next->state == 0)/* -1 unrunnable, 0 runnable, >0 stopped */ { /* switch to Next process */ asm volatile ( "Pushl %%ebp\n\t" /* save ebp */ "movl %%esp,%0\n\t" /* save esp */ "movl %2,%%esp\n\t" /* restore esp */ "movl $1f,%1\n\t" /* save eip */ "PUSHL %3\n\t " " ret\n\t " /* restore eip */ "1:\t" /* next process start here */ "POPL&NBSP;%%EBP \n\t " : " =m " (PREV->THREAD.SP)," =m " (prev- >THREAD.IP) : "M" (NEXT->THREAD.SP), "M" ( NEXT->THREAD.IP) ); my_current_task = next; &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;PRINTK (kern_notice ">>>switch %d to %d<<<\ n ", Prev->pid,next->pid); } else { next->state = 0; &NBSP;&NBSP;MY_CURRENT_TASK&NBSP;=&NBSP;NEXT;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;PRINTK (KERN_NOTICE ">>>switch %d to %d<<<\n", Prev->pid,next->pid); /* switch to new process */ asm volatile ( "pushl %%ebp\n\t" /* save ebp */ "movl %%esp,%0\n\t" /* save esp */ "movl %2,%%esp\n\t" /* restore esp */ "movl % 2,%%ebp\n\t " /* restore ebp */ "movl $1f,%1\n\t" /* save eip * / "pushl %3\n\t" "ret\n\t" /* restore eip */ : "=m" (PREV->THREAD.SP), "=m" (prev- >THREAD.IP) : "M" (NEXT->THREAD.SP), "M" ( NEXT->THREAD.IP) ); } return;}
3. Process start-up and switching mechanism
The operating system manages the process management schedule mainly through the Process Control block (PCB)
typedef struct pcb{int pid; Volatile long state;/*-1 unrunnable, 0 runnable, >0 stopped */char stack[kernel_stack_size]; /* Cpu-specific State of the This task */struct thread thread; unsigned longtask_entry; struct PCB *next;} TPCB;
When the kernel starts, in the void __init my_start_kernel (void) function, 4 processes are generated first, and the first process in the process queue is passed through a statement
Task[pid].task_entry = Task[pid].thread.ip = (unsigned long) my_process;
is set to My_process, and the process is process No. 0, after which 3 processes pass Task[i].next = Task[i-1].next; the statements are all my_process.
After entering the respective process, according to My_need_sched to determine the running state of the process and scheduling, this state in the My_timer_handler function according to the timing situation set, once the time is satisfied will generate interrupt notification process, the process to do the corresponding operation.
The process state is determined when an interrupt is generated, if next->state = = 0, the next process can be run, then the code is compiled by
asm volatile ( "pushl %%ebp\n\ T " /* save ebp */ " Movl %%esp,%0\n\t " /* save esp */ " Movl %2,%%esp\n\t " /* restore esp */ "movl $1f,%1\n\t" /* save eip */ "pushl %3\n\t" "ret\n\t" /* restore eip */ "1:\t" /* Next process start here */ "popl %%ebp\n\t" : "=m" (PREV->THREAD.SP), "=m" (PREV->THREAD.IP) : "M" (NEXT->THREAD.SP), "M" (NEXT->THREAD.IP) );
Saves the execution environment of the current process to the stack and moves to the end of the process queue, loads the next IP that is in progress, and starts executing the next process.
If the status of the next process is not executable, set it to the executable state ready to accept the schedule, save its current execution environment and move to the tail of the process queue and return. The NO. 0 process then executes the executable process in the scheduling process queue.
4. Summary:
In the process scheduling algorithm of the time slice rotation multi-channel program, the time slice is determined by the timer, and the time slice is rotated by the interrupt. The process scheduling is done in a simple sequential way through the process queue.
This article is from "Whispering Autumn Wind" blog, please be sure to keep this source http://xjhznick.blog.51cto.com/3608584/1620535
Analysis of process start-up and process switching mechanism through a simple time slice rotation multi-channel program