实验部分:

首先运行结果截图

代码分析:

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

/* CPU-specific state of this task */

struct Thread {

unsigned long           ip;

unsigned long           sp;

};

typedef struct PCB{

int pid;//进程的id用pid表示

volatile long state;  /* -1 unrunnable, 0 runnable, >0 stopped */ //进程状态,-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);

mymian.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];

tPCB * my_current_task = NULL;//当前task指针

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;//初始化0号进程

task[pid].state = 0;/* -1 unrunnable, 0 runnable, >0 stopped *///状态是运行

task[pid].task_entry = task[pid].thread.ip = (unsigned long)my_process;//入口是myprocess

task[pid].thread.sp = (unsigned long)&task[pid].stack[KERNEL_STACK_SIZE-1];//堆栈栈顶

task[pid].next = &task[pid];//刚启动时只有它自己,所以next也指向它自己

/*fork more process *///创建更多进程

for(i=1;i<MAX_TASK_NUM;i++)

{

memcpy(&task[i],&task[0],sizeof(tPCB));//把0号进程的状态复制给下一个进程

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] *///开始执行0号进程

pid = 0;

my_current_task = &task[pid];

asm volatile(//此处为嵌入式汇编代码

"movl %1,%%esp\n\t"    /* set task[pid].thread.sp to esp *///将thread.sp复制给esp

"pushl %1\n\t"                /* push ebp *///当前栈是空的,esp=ebp,所以压栈sep就是压栈ebp

"pushl %0\n\t"                /* push task[pid].thread.ip *///将ip压栈

"ret\n\t"                      /* pop task[pid].thread.ip to eip *///将ip弹栈,即myprocess的头部,也就是0号进程正式开始启动

"popl %%ebp\n\t"//弹栈

:

: "c" (task[pid].thread.ip),"d" (task[pid].thread.sp)        /* input c or d mean %ecx/%edx*///c是%0,即为ip;d是%1,即为sp.

);

}   //内核初始化完成,0号进程开始执行

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)                              //1为需要调度

{

my_need_sched = 0;

my_schedule();

}

printk(KERN_NOTICE "this is process %d +\n",my_current_task->pid);

}

}

}

Myinterrupt

/*

*  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 unrunnable, 0 runnable, >0 stopped *///切换进程

    {

             /* switch to next process */

             asm volatile(   

                 "pushl %%ebp\n\t"             /* save ebp */

                 "movl %%esp,%0\n\t"    /* save esp *///存到内存的prev->thread.sp

                 "movl %2,%%esp\n\t"     /* restore  esp *///存到内存的next->thread.sp

                 "movl $1f,%1\n\t"       /* save eip */        //标号1: 的位置放在内存的prev->thread.ip

                 "pushl %3\n\t"  //存到内存的next->thread.ip

                 "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 */

             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;    

}

总结部分:

本周要点:

  1. 计算机的三大法宝:存储程序计算机;函数调用堆栈;中断机制
  2. 堆栈

最原始的计算机是没有堆栈的概念的,出现高级语言以后才有了堆栈。堆栈是记录路径和参数的空间。

函数调用框架

传递参数(只适用于32位的x86)

保存返回地址

提供局部变量空间

  3.堆栈寄存器

esp,堆栈栈顶指针,stack pointer

eip,  堆栈基址指针,base pointer

  4.堆栈操作

push,压栈减4字节

pop,弹栈加4字节

  5.其他寄存器

eip,不管是顺序执行,还是跳转,分支,都总是指向下一条应该执行的语句。

call,将当前eip的值压栈,并将eip的值改为函数入口的下一条指令的地址值。

ret,将eip的值弹栈放入eip中。

  6.建立函数堆栈框架

push %ebp

movl %esp,%ebp

拆除函数堆栈框架

movl %ebp.%esp

pop %ebp

  7.重点理解myinterruput.c里进程切换的代码。(切换进程指的是下一个切换上执行的进程)

  分成两种情况,第一种是切换到的进程是执行过的进程,第二种是切换到的进程是新进程。首先第一种,先将当前进程的ebp压栈,然后将当前进程的栈顶指针esp保存到链表结构当前进程prev->thread.sp中,再将链表中切换的进程的next->thread.sp 复制给栈顶指针esp.将链表中当前进程prev->thread.ip存入函数的入口的值,再将切换进程的next->thread.ip压栈。然后第二种,先建好链表,再执行上述过程。

linux及安全第二周总结——20135227黄晓妍的更多相关文章

  1. linux及安全第八周总结——20135227黄晓妍

    实验部分 实验环境搭建 -rm menu -rf git clone https://github.com/megnning/menu.git cd menu make rootfs qemu -ke ...

  2. linux及安全第七周总结——20135227黄晓妍

    实验部分 首先clone最新的menu 我们可以看到,test.c里多了一个exec的功能,它的代码和fork基本一致,多了一项加载hello rootfs也有一些变化 执行一下exec 让我们启动一 ...

  3. linux安全第一周总结——20135227黄晓妍

    实验部分: 我将源代码做了修改,将其中一个数字修改为我学号27 2.在实验楼环境下将其保存为text.c并将其编译,得到text.s 3.将.开头的多余的语句删去了之后,我得到了32位环境的汇编代码 ...

  4. linux及安全第三周总结——20135227黄晓妍

    总结部分: Linux内核源代码: Arch 支持不同cpu的源代码:主要关注x86 Init   内核启动的相关代码:主要关注main.c,整个Linux内核启动代码start_kernel函数 K ...

  5. linux及安全第六周总结——20135227黄晓妍

    总结部分: 操作系统内核三大功能: 进程管理,内存管理,文件系统 最核心的是进程管理 为了管理,首先要对每一个进程进行描述.进程描述符提供了所有内核需要了解的信息. 进程控制模块:task_struc ...

  6. linux及安全第五周总结——20135227黄晓妍

    (注意:本文总结备份中有较多我手写笔记的图片,其中重要的部分打出来了.本文对分析system_call对应的汇编代码的工作过程,系统调用处理过程”的理解,以及流程图都写在实验部分.) 实验部分 使用g ...

  7. linux及安全第四周总结——20135227黄晓妍

    总结部分: 用户态和内核态: 前提知识:cpu有几种不同指令执行的级别 用户态:代码的掌控范围受限制 内核态:高级别,代码课执行特权指令,访问任意物理地址. 权限设置的意义:没有的话,系统容易啊崩溃, ...

  8. linux及安全期中总结——20135227黄晓妍

    Linux及安全期中总结 黄晓妍 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ...

  9. linux及安全《Linux内核设计与实现》第二章——20135227黄晓妍

    第二章:从内核出发 2.1获取源代码 2.1.1使用git Git:内核开发者们用来管理Linux内核源代码的控制系统. 我们使用git来下载和管理Linux源代码. 2.1.2安装内核源代码(如果使 ...

随机推荐

  1. Vue基础-在模板中使用过滤器

    Vue 测试版本:Vue.js v2.5.13 官网给了过滤器的两种使用方式: 1.你可以在一个组件的选项中定义本地的过滤器: 结合实例,我给两个代码: <div id="app&qu ...

  2. centos 7.5 最小化安装

    参考:https://www.tecmint.com/centos-7-installation/ ================================================== ...

  3. python基础-第十一篇-11.2DOM为文档操作

    文档对象模型(DOM)是一种用于HTML和XML文档的编程接口 节点类型 12种节点类型都有NodeType属性来表明节点类型 节点关系 <div id="t"> &l ...

  4. 《OVN Logical Flows and ovn-trace》翻译

    在本篇文章中,我将解释什么是Logical Flow以及如何使用ovn-trace去更好地理解它们.同时,我也会用一些例子来解释,为什么使用Logical Flow这种抽象模型能让新特性的添加变得出乎 ...

  5. Spring-BeanFactory容器

    Spring的BeanFactory容器 这是Spring中最简单地容器,它主要的功能是为依赖注入(DI)提供支持.这个容器接口在org.springframework.beans.factory.B ...

  6. python 添加进度条

    安装: pip install tqdm使用: from tqdm import tqdm import time for i in tqdm(rang(10)): time.sleep(0.1)

  7. java 多线程 day08 java5多线程新特性

    /** * Created by chengtao on 17/12/3. */public class Thread0801_java5_Atomaic { /* 三个包: http://tool. ...

  8. ASP.NET的优点

    ASP.NET 是一个统一的 Web 开发平台,它提供开发人员创建企业级 Web 应用程序所需的服务.尽管 ASP.NET 的语法基本上与 ASP 兼容,但是它还提供了一个新的编程模型和基础结构以提高 ...

  9. Charles 抓包工具的使用

    抓包工具有很多,目前用过的有Charles, Fiddler, burpsuite.下面主要是Charles 的应用实例. 一. 用Charles抓包 1. PC 抓包 打开Charles, 确保“录 ...

  10. undefined reference to `__sync_bool_compare_and_swap_4

    然后开始glibc的编译工作. 你必须设定march这个参数才行,要不然会出现“undefined reference to `__sync_bool_compare_and_swap_4′.”这个错 ...