Chen Chaojan Original works reproduced please specify the source "Linux kernel Analysis" MOOC course http://mooc.study.163.com/course/USTC-1000029000
First, using the virtual machine of the experimental building, observe the relationship between the mykernel of a dead loop and the clock interrupt.
步骤:
cd LinuxKernel/linux-3.9.4qemu -kernel arch/x86/boot/bzImage
Execution effects such as
Paste_image.png
View MYMAIN.C Now:
Paste_image.png
See Myinterrupt.c again:
Paste_image.png
From the execution effect, the My_timer_handler and My_start_kernel cycle is really alternating, about 100,000 times per cycle will be executed once timer_handler.
Second, for only the dead loop Mykernel to add the time slice function and recompile, observe the new Mykernel behavior
First clone mengning/mykernel
, replace MYMAIN.C and myinterrupt.c, add Mypcb.h:
cd ~/LinuxKernel/linux-3.9.4
git clone https://github.com/mengning/mykernel.git mykernel_new
cd mykernel_new
cp mymain.c myinterrupt.c mypcb.h ../mykernel
cd ..
Then run make
the recompile Mykernel:
Paste_image.png
And then run qemu -kernel arch/x86/boot/bzImage
:
It is not difficult to observe the new Mykernel behavior, total 0 1 2 3 A total of four process, the new Mykernel executes n process for a certain time, will change to (n+1)% 4th process continues to execute,
will be printed at the replacement >>> my_schedule <<<
, and>>> switch n to (n+1)%4 <<<
Such as:
The 3rd process cuts to the moment of number No. 0:
Paste_image.png
The 1th process cuts to the moment of number 2nd:
Paste_image.png
Knowing the behavior of Mykernel, here's how mymain.c and myinterrupt.c do it:
You can first see a constant definition on line 10th of Mypcb.h
#define MAX_TASK_NUM 4
Then observe the Mykernel execution entry function My_start_kernel the MYMAIN.C loop starting from line 36th
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 = (UnsignedLong) &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*/);
In combination with code comments, it can be concluded that 36 lines of code initialize the PCB of process No. 0, and set the processes to runnable, and the execution entry is set to My_process in a 36-line loop, which is initialized with 1 2 3rd, set to Unrunnable, and 0 The next pointer of 1 2 3rd process is set to the address of 1 2 3 0 respectively (form a single loop linked list) and set the respective THREAD.SP pointers to the starting address of their respective kernel stacks. Then in the assembly code of L48 to L55, the current ESP is set to TASK[0].THREAD.SP, which is incorporated into the stack save,
The My_process function at the Thread.ip address of process No. 0 is then indirectly push/ret by means of the method. followed by the pop %ebp
first executed code of the next scheduled process
To the My_process function, each cycle 10000000 thereafter, first Judge My_need_sched, if the previous My_timer_handler will my_need_schedule 1 (every 1000 clock interrupt), then enter My_ Schedule and put my_need_sched 0;
Now is the time to dispatch the My_schedule function:
If Next process executes for the first time (state = =-1), the process in the Else branch is pressed:
Into the stack ebp, save the current ESP to PREV->THREAD.SP, EIP to Prev->thread.ip, then set EBP, esp to NEXT->THREAD.SP, and then the same method as the No. 0 process (push Thread.ip; RET) to call the My_process function.
If Next process is dispatched again (state = = 0), it is executed in rows 56 through 69.
Summary: The implementation of the scheduling needs to save the current task/process field (EBP/EIP), and then with the clock interrupt, for the first time to be dispatched and again by the scheduling of the situation processing.
Linux kernel Design second week Learning summary complete a simple time slice rotation multi-channel program kernel code