20233808《Linux内核原理与分析》第三周作业

一、与chatgpt的对话

https://chat.openai.com/share/7b05ea26-3948-4139-ac91-213b1ffc0730
 

二、实验完成情况

1.原始内核

使用实验楼提供的内容编译和自定义一个内核

# 注意路径是区分大小的
$ cd ~/LinuxKernel/linux-3.9.4
$ rm -rf mykernel
$ patch -p1 < ../mykernel_for_linux3.9.4sc.patch
#这个命令将一个名为 mykernel_for_linux3.9.4sc.patch 的补丁应用到Linux内核源代码中
$ make allnoconfig
#这个命令将一个名为 mykernel_for_linux3.9.4sc.patch 的补丁应用到Linux内核源代码中
$ make
$ qemu -kernel arch/x86/boot/bzImage
#使用QEMU虚拟机启动编译后的内核

qemu启动编译后的内核,可以看到陷入死循环。

2.更改代码

使用git-hub上提供的代码,以下代码段包含了代码分析

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 task[MAX_TASK_NUM];
/*定义了一个名为task的tPCB结构数组,用于表示自定义内核中的任务或进程的控制块*/
volatile int my_need_sched = 0;
/*初始化了一个volatile整数my_need_sched*/
tPCB * my_current_task = NULL;
/*初始化了一个名为my_current_task的指针*/
void my_process(void);


void __init my_start_kernel(void)  
{
    int pid = 0;
    int i;
    /*初始化task数组中的第一个任务(进程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;  
    /*将进程0的task_entry和thread.ip设置为指向my_process函数的地址*/
    task[pid].thread.sp = (unsigned long)&task[pid].stack[KERNEL_STACK_SIZE-1];  
    /*将进程0的堆栈指针(thread.sp)设置为堆栈的末尾*/
    task[pid].next = &task[pid];  /*将进程0的next指针指向自己,因为此时只有一个进程*/
    /*fork more process */
    for(i=1;i<MAX_TASK_NUM;i++)  /*使用for循环,从i = 1开始,创建更多的进程*/
    {
        memcpy(&task[i],&task[0],sizeof(tPCB)); /*复制进程0的PCB以创建新的进程*/
        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];
    }
    /*启动进程0 */
    pid = 0;
    my_current_task = &task[pid];  
    #将my_current_task指针设置为指向进程0,表示当前运行的任务是进程0
	asm volatile(
    	"movl %1,%%esp\n\t" 	/*将进程0的堆栈指针的值加载到寄存器esp中 */
    	"pushl %1\n\t" 	        /* 将相同的堆栈指针值再次推送到堆栈 */
    	"pushl %0\n\t" 	        /* 将进程0的入口地址(task[pid].thread.ip)推送到堆栈 */
    	"ret\n\t" 	            /* 弹出堆栈中的地址并跳转到该地址 */
    	"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
/*
 *  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%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 不运行, 0 运行, >0 暂停 */
    {
    	my_current_task = next; 
    	printk(KERN_NOTICE ">>>switch %d to %d<<<\n",prev->pid,next->pid);  
    /* 使用内联汇编切换到下一个任务的执行上下文,包括堆栈指针(esp)和指令指针(eip) */
    	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);
    	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;	
}
mypcb.h
/*
 *  linux/mykernel/mypcb.h
 *
 *  Kernel internal PCB types
 *
 *  Copyright (C) 2013  Mengning
 *
 */
/*定义了最大任务(或进程)数量*/
#define MAX_TASK_NUM        4  
/*定义了内核堆栈的大小*/
#define KERNEL_STACK_SIZE   1024*8  

/* 数据块定义 */
struct Thread {
    unsigned long		ip;
    unsigned long		sp;
};
/*数据块定义*/
typedef struct PCB{
    int pid;
    volatile long state;	/* -1 不运行, 0 运行, >0 停止 */
    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); /*声明了一个名为my_schedule的函数*/

3.更改后的内核

可以看到跳出死循环,变成多进程执行

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值