Xujianguo Original works reproduced please specify the source
"Linux kernel Analysis" MOOC course http://mooc.study.163.com/course/USTC-1000029000 "
————————————————————————————————————————————————————————————————
Experimental Purpose:
Run and analyze a streamlined operating system kernel to understand how the operating system works;
Experimental steps:
1. Open the shell using the virtual machine of the lab building:
2.CD Mykernel You can see the code MYMAIN.C and myinterrupt.c of the contents of the Qemu window output;
3. Complete a simple time slice rotation multi-channel program kernel code, the code see in the video, or from Mykernel find.
Modify related documents MYMAIN.C and MYINTERRUPT.C, complete relevant kernel code;
Add process Dispatch header file Mypcb.h, refine and adjust the experiment.
4. Commissioning and testing:
Cd.. Return to Parent directory (method from discussion area, thank you);
Make compile and test.
5. Verification and testing
Qemu-kernel Arch/x86/boot/bzimage
    
Experimental Analysis:
  This small experiment is mainly controlled by the following documents:
Mymain.c,myinterrupt.c,mypcb.h
1. Mypcb.h
Important header file, which mainly defines the declaration of the Process Control structure PCB, kernel stack size and scheduling algorithm.
/* 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;
2.myinterrupt.c
The main definition is the time interrupt function and the dispatch function.
Time Interrupt handler function:
void My_timer_handler (void)
{
#if 1
if (time_count%1000 = = 0 && my_need_sched! = 1)
{
PRINTK (kern_notice ">>>my_timer_handler here<<<\n");
my_need_sched = 1;
}
Time_count + +;
#endif
Return
}/* here in order to visibly see the processing effect of interrupts. The experimental results can be enhanced by adjusting the modulo operation. */
Dispatch function:
...............................................
/* 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%%ebp\n\t"
: "=m" (PREV->THREAD.SP), "=m" (PREV->THREAD.IP)
: "M" (NEXT->THREAD.SP), "M" (NEXT->THREAD.IP)
);
My_current_task = Next;
PRINTK (kern_notice ">>>switch%d to%d<<<\n", prev->pid,next->pid);
.............................................
3.mymain.c
Is the entry file for this experiment, primarily defining initialization and execution functions and sample process functions.
Initialization process:
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];
Example process functions:
void my_process (void)
{
int i = 0;
while (1)
{
i++;
if (i%10000000 = = 0)
{
PRINTK (Kern_notice "This is process%d-\n", my_current_task->pid);
if (my_need_sched = = 1)
{
my_need_sched = 0;
My_schedule ();
}
PRINTK (Kern_notice "This is process%d +\n", my_current_task->pid);
}
}
}
   4. Analysis of process start-up and process switching mechanism
Mainly from the My_start_kernel function into the process, through the above initialization process for the initialization and invocation of number No. 0 process;
A similar approach was used to build n PCB processes:
One of the important codes:
 ..................
 task[i].state = -1;//进程初始化为unrunnable 状态
 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];
....................
The inline assembly was used to complete the start of process No. 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*/
);
Let ESP point to the top of the 0 process stack (at the same time the bottom of the stack), the stack of EBP into the stack, call the my_process entry address, jump to my_process.
   Use If....else to control process switching:
next->state = 0;
My_current_task = Next;
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)
);
  Change the state of the current process to 0 (runnable[), and modify the PCB structure that the current running process pointer points to, and execute the inline assembly statement after execution, for process switching operations. The process scheduler function is called. Reverse completes the return operation. The RET instruction pops the value from the stack to the EIP and makes the stack smaller.
Summarize:
The computer we use in real life uses different scheduling algorithms due to various needs and requirements, but the basic switching process is similar, but more complex and more efficient. The use of interrupt mechanisms also enables computers to perform more complex calculations and analyses. A process is defined as a separate program that runs in its own virtual address space, and from the operating system's point of view, everything that runs on the system can be called a process. According to the function of the process and the running program classification, the process can be divided into two categories: system process: can perform memory resource allocation and process switching management, and the process is not user intervention, even if the root user can not interfere with the operation of the system process; user processes: By executing user programs, A process generated by a system program outside of an application or kernel that can be run or shut down Under the user's control. 
User-level applications, through system calls, into the kernel space. The kernel also saves some registers, variables, etc. of the user process so that the system call returns to the user space to continue execution. The "process context" is the value of all registers of the CPU, the state of the process, and the contents on the stack when a process executes, and when the kernel needs to switch to another process, it needs to save all the state of the current process, that is, to save the process context of the current process so that it can execute the process again. Ability to resume the state of the switchover and continue execution.
Reference Documentation:
Http://blog.chinaunix.net/uid-27717694-id-3803944.html
Http://www.2cto.com/os/201412/359261.html
Some understanding of operating system process switching