韓巖___第2課___《linux內核分析》MOOC課


題目:簡單的時間片輪轉多道程序內核代碼

一、簡單的時鐘中斷程序

1、代碼mymain.c

#include<linux/types.h>

#include<linux/module.h>

#include<linux/proc_fs.h>

#include<linux/kernel.h>

#include<linux/syscalls.h>

#include<linux/stackprotector.h>

#include<linux/string.h>

#include<linux/ctype.h>

#include<linux/delay.h>

#include<linux/ioport.h>

#include<linux/init.h>

#include<linux/initrd.h>

#include<linux/bootmem.h>

#include<linux/acpi.h>

#include<linux/tty.h>

#include<linux/percpu.h>

#include<linux/kmod.h>

#include<linux/vmalloc.h>

#include<linux/kernel_stat.h>

#include<linux/start_kernel.h>

#include<linux/security.h>

#include<linux/smp.h>

#include<linux/profile.h>

#include<linux/rcupdate.h>

#include<linux/moduleparam.h>

#include<linux/kallsyms.h>

#include<linux/writeback.h>

#include<linux/cpu.h>

#include<linux/cpuset.h>

#include<linux/cgroup.h>

#include<linux/efi.h>

#include<linux/tick.h>

#include <linux/interrupt.h>

#include<linux/taskstats_kern.h>

#include<linux/delayacct.h>

#include<linux/unistd.h>

#include<linux/rmap.h>

#include<linux/mempolicy.h>

#include<linux/key.h>

#include<linux/buffer_head.h>

#include<linux/page_cgroup.h>

#include<linux/debug_locks.h>

#include<linux/debugobjects.h>

#include<linux/lockdep.h>

#include<linux/kmemleak.h>

#include<linux/pid_namespace.h>

#include<linux/device.h>

#include<linux/kthread.h>

#include<linux/sched.h>

#include<linux/signal.h>

#include<linux/idr.h>

#include<linux/kgdb.h>

#include<linux/ftrace.h>

#include<linux/async.h>

#include<linux/kmemcheck.h>

#include<linux/sfi.h>

#include<linux/shmem_fs.h>

#include<linux/slab.h>

#include<linux/perf_event.h>

#include<linux/file.h>

#include<linux/ptrace.h>

#include<linux/blkdev.h>

#include<linux/elevator.h>

 

#include<asm/io.h>

#include<asm/bugs.h>

#include<asm/setup.h>

#include<asm/sections.h>

#include<asm/cacheflush.h>

 

#ifdefCONFIG_X86_LOCAL_APIC

#include<asm/smp.h>

#endif

 

void__init my_start_kernel(void)

{

    int i = 0;

    while(1)

    {

        i++;

        if(i%10000000 == 0)

            printk(KERN_NOTICE"my_start_kernel here  %d\n",i);

           

    }

}

2、myinterupt.c程序代碼如下:

#include<linux/kernel_stat.h>

#include<linux/export.h>

#include<linux/interrupt.h>

#include<linux/percpu.h>

#include<linux/init.h>

#include<linux/mm.h>

#include<linux/swap.h>

#include<linux/pid_namespace.h>

#include<linux/notifier.h>

#include<linux/thread_info.h>

#include<linux/time.h>

#include<linux/jiffies.h>

#include<linux/posix-timers.h>

#include<linux/cpu.h>

#include<linux/syscalls.h>

#include<linux/delay.h>

#include<linux/tick.h>

#include<linux/kallsyms.h>

#include<linux/irq_work.h>

#include<linux/sched.h>

#include<linux/sched/sysctl.h>

#include<linux/slab.h>

 

#include<asm/uaccess.h>

#include<asm/unistd.h>

#include<asm/div64.h>

#include<asm/timex.h>

#include<asm/io.h>

 

#defineCREATE_TRACE_POINTS

#include<trace/events/timer.h>

 

/*

 * Called by timer interrupt.

 */

voidmy_timer_handler(void)

{

      printk(KERN_NOTICE"\n>>>>>my_timer_handler here<<<<<\n\n");

}

3、運行結果:


二、簡單的時間片輪轉多道程序

1、mypcb.h

#defineMAX_TASK_NUM        4

#defineKERNEL_STACK_SIZE   1024*8

 

/*CPU-specific state of this task */

structThread {

    unsigned long                  ip;

    unsigned long                  sp;

};

 

typedefstruct 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;

 

voidmy_schedule(void);

以上程序的結構爲:

結構體包括:

Ø  1個pid位

Ø  1個state位

Ø  1個堆棧

Ø  1個線程(包括ip、sp)

Ø  1個入口與1個next位

 

2、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"

 

tPCBtask[MAX_TASK_NUM];

tPCB *my_current_task = NULL;

volatileint my_need_sched = 0;

 

voidmy_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, 0runnable, >0 stopped */

    task[pid].task_entry = task[pid].thread.ip= (unsigned long)my_process;

    task[pid].thread.sp = (unsignedlong)&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 = (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"          /* settask[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*/

);

}  

voidmy_process(void)

{

    int i = 0;

    while(1)

    {

        i++;

        if(i%10000000 == 0)

        {

            printk(KERN_NOTICE "this isprocess %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);

        }    

    }

}



 

3、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"

 

externtPCB task[MAX_TASK_NUM];

externtPCB * my_current_task;

externvolatile int my_need_sched;

volatileint time_count = 0;

 

/*

 * Called by timer interrupt.

 * it runs in the name of current runningprocess,

 * so it use kernel stack of current runningprocess

 */

voidmy_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;       

}

 

voidmy_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, 0runnable, >0 stopped */

    {

       /*switch to next process */

       asmvolatile(       

            "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);     

    }

    else

    {

        next->state = 0;

        my_current_task = next;

        printk(KERN_NOTICE">>>switch %d to%d<<<\n",prev->pid,next->pid);

       /*switch to new process */

       asmvolatile(       

            "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; 

}


4、編譯以上代碼:

gcc–c 文件名.c 生成目標文件後

cdLinuxKernel/linux-3.9.4

qemu-kernel arch/x86/boot/bzImage


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章