2019-2020-1 20199303 "Linux kernel principle and Analysis" in the third week of work

How the operating system works

In addition to storing the computer program and the call stack mechanism function, there is a very basic concept is interrupted, the three key mechanism method can be called three magic computer: stored-program computer, function calls, interrupts

Stack effects: frame recorded as a function call, passing function parameters, return value address, it provides functions inside the local amount of storage space.

Stack registers associated ESP: Stack pointer stack stack EBP: base address pointer to the stack stack bottom

Stack operations: push pop

experiment procedure

Sequentially input
cd ~ / LinuxKernel / linux-3.9.4

$ rm -rf mykernel

$ patch -p1 < ../mykernel_for_linux3.9.4sc.patch

$ make allnoconfig

$ make

$ qemu -kernel arch/x86/boot/bzImage


Can see the kernel boot effect
mymain.c may output time per 100,000 my start kernel here, periodically generates an interrupt the clock signal while executing code in myinterrupt.c.

Modify the code and then press the test requirements as follows
mypcb.h:
#define MAX_TASK_NUM. 4
#define KERNEL_STACK_SIZE 1024 *. 8

/* CPU-specific state of this task */
struct Thread {
unsigned long       ip;
unsigned long       sp;
};

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 long   task_entry;
struct PCB *next;
}tPCB;

void my_schedule(void);   

mymain.c:
#include <linux/types.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/tty.h>
#include <linux/vmalloc.h>

#include "mypcb.h"

tPCB 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)
    {
        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);
    }     
}
}

myinterrupt.c:
#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%1000 == 0 && my_need_sched != 1)
{
    printk(KERN_NOTICE ">>>my_timer_handler here<<<\n");
    my_need_sched = 1;
} 
time_count ++ ;  
#endif
return;     
}

void my_schedule(void)
{
tPCB * next;
tPCB * prev;

if(my_current_task == NULL 
    || my_current_task->next == NULL)
{
    return;
}
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 */
{
    my_current_task = next; 
    printk(KERN_NOTICE ">>>switch %d to %d<<<\n",prev->pid,next->pid);  
    /* 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)
    ); 

}
else
{
    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)
    );          
}   
return; 
}

After completion directory

Operating results for the

In my_process (void) function, print "this is process% d" each 10000000, if my_need_sched interrupt 1:00, execution myinerrupt in my_schedule () trigger.

Guess you like

Origin www.cnblogs.com/besti-20199303/p/11608958.html