张文俊 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

一、第二周学习内容总结

1、计算机工作“三大法宝”

首先,计算机工作原理最重要的三个内容就是:存储程序计算机工作模型、中断机制和函数调用堆栈。

存储程序计算机工作模型是计算机系统最最基础性的逻辑结构;

中断机制是多道程序操作系统的基点,没有中断机制程序只能从头一直运行结束才有可能开始运行其他程序;

函数调用堆栈是高级语言得以运行的基础,有了高级语言及函数后,堆栈成为了计算机的基础功能,函数参数传递机制和局部变量存储。

2、详细介绍函数调用堆栈

首先,堆栈是C语言程序运行时必须的一个记录调用路径和参数的空间,即CPU内已经集成好了很多功能。

堆栈含以下元素:

函数调用框架、传递参数、保存返回地址、提供局部变量空间、C语言编译器对堆栈的使用有一套的规则。

了解堆栈存在的目的和编译器对堆栈使用的规则是理解操作系统一些关键性代码的基础。

其次,堆栈相关的寄存器常用的共有四种,esp、ebp、push、pop。详细解释如下:

esp,堆栈指针,指向栈顶;

ebp,基址指针,指向栈底,在C语言中用作记录当前函数调用基址;

push,栈顶地址减少4个字节,从低地址向高地址;

pop,栈顶地址增加4个字节,从高地址向低地址;

最后,课程介绍了函数参数的传递与框架——

(1)建立框架,即call指令

相当于

push %ebp

movl %esp,%ebp

cs:eip原来的值指向call下一条指令,该值被保存到栈顶cs:eip的值指向function的入口地址

(2)执行函数主体代码

(3)拆除框架

相当于

movl %ebp,%esp

pop %ebp

ret

函数的返回值通过eax寄存器传递

3、参数传递

这里以老师在课堂上举出的例子:

#include <stdio.h>

void p1(char c)

{

printf("%c",c);

}

int p2(int x,int y)

{

return x+y;

}

int main(void)

{

char c ='a';

int x,y;

x =1;

y =2;

p1(c);

z = p2(x,y);

printf("%d = %d+%d",z,x,y);

}

首先,观察P2的堆栈框架:

这里,使用变址寻址方式,将x+y的值赋给eax。

然后,我们观察main是如何传递参数给P2的:

和main中的局部变量:

可以看到,汇编代码中用变址寻址把y的值和x的值存放到堆栈中,然后进行局部变量调用。

4、C代码中嵌入汇编代码

____asm____

(

汇编语句模板:

输入部分:

输出部分:

破坏描述部分:

);

二、实验二内容

本次实验内容是在mykernel基础上构造一个简单的操作系统内核。

首先我们cd进入LinuxKernel/linux-3.9.4文件,执行qemu -kernel arch/x86/boot/bzImage,可以看到窗口弹出如下:

然后,我们查看mymain.c和myinterrrupt.c文件:

可以发现,mymain是系统中唯一的进程,函数主要部分是my_start_kernel。每循环10万次,就打印一次my_start_kernel here.

myinterrupt是时间中断处理程序,每进行一次就会发生一次时钟处理中断,每次时钟中断都调用printk并输出。

程序分析:

mypcb.h

#define MAX_TASK_NUM 4

#define KERNEL_STACK_SIZE 1024*8

/* CPU-specific state of this task */

struct Thread {

unsigned long ip;//保存eip

unsigned long sp;//保存esp

};

typedef struct PCB{

//用于表示一个进程,定义了进程管理相关的数据结构

int pid;

volatile long state; /* 定义进程的状态:-1 不可运行, 0 可运行, >0 停止 */

char stack[KERNEL_STACK_SIZE];

//内核堆栈

struct Thread thread;

unsigned long task_entry; //指定进程入口

struct PCB *next;//进程链表

}tPCB;

void my_schedule(void);//调用了my_schedule,表示调度器

mymain.c

void my_timer_handler(void)

{

#if 1

if(time_count%1000 == 0 && my_need_sched != 1)//设置时间片的大小,时间片用完时设置一下调度标志。当时钟中断发生1000次,并且my_need_sched!=1时,把my_need_sched赋为1。当进程发现my_need_sched=1时,就会执行my_schedule。

{

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 //task为空,即发生错误时返回

|| my_current_task->next == NULL)

{

return;

}

printk(KERN_NOTICE ">>>my_schedule<<<\n");

/* schedule */

next = my_current_task->next; //将当前进程的下一个进程赋给next

prev = my_current_task;//当前进程为prev

if(next->state == 0)

/* -1 unrunnable, 0 runnable, >0 stopped */

{

//在两个正在执行的进程之间做上下文切换

asm volatile( "pushl %%ebp\n\t"

/* 保存当前进程的ebp */

"movl %%esp,%0\n\t" /* 保存当前进程的esp */

"movl %2,%%esp\n\t" /* 重新记录要跳转进程的esp,将下一进程中的sp放入esp中 */

"movl $1f,%1\n\t" /* $1f指标号1:的代码在内存中存储的地址,即保存当前的eip */

"pushl %3\n\t" //将下一进程的eip压入栈,%3为 next->thread.ip

"ret\n\t" /* 记录要跳转进程的eip */

"1:\t" /* 下一个进程开始执行 */

"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 /* 与上一段代码不同的是如果下一个进程为新进程时,就运用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" /* 保存当前进程的ebp */ "movl %%esp,%0\n\t" /* 保存当前进程的esp */ "movl %2,%%esp\n\t" /* 重新记录要跳转进程的esp */

"movl %2,%%ebp\n\t" /* 重新记录要跳转进程的ebp */ "movl $1f,%1\n\t" /* 保存当前eip */ "pushl %3\n\t" "ret\n\t" /* 重新记录要跳转进程的eip */

: "=m" (prev->thread.sp),"=m" (prev->thread.ip)

: "m" (next->thread.sp),"m" (next->thread.ip) ); }

return; }

精简内核运行结果:

三、总结

操作系统是管理计算机系统的全部硬件资源包括软件资源及数据资源;控制程序运行;改善人机界面;为其它应用软件提供支持等,使计算机系统所有资源最大限度地发挥作用,为用户提供方便有效的服务界面。

Linux是一个多进程的操作系统,所以,其他的进程必须等到正在运行的进程空闲CPU后才能运行。

当正在运行的进程等待其他的系统资源时,Linux内核将取得CPU的控制权,并将CPU分配给其他正在等待的进程,这就是进程切换。

内核中的调度算法决定将CPU分配给哪一个进程。

进程是动态执行的实体,内核是进程的管理者。

进程不但包括程序的指令和数据,而且包括程序计数器和CPU的所有寄存器以及存储临时数据的进程堆栈。

所以,正在执行的进程包括处理器当前的一切活动。

进程既可以在用户态下运行,也能在内核下运行,只是内核提供了一些用户态没有的核心服务,

因此进程在访问这些服务时会产生中断,必须进行用户态与内核态的切换。

“Linux内核分析”实验二报告的更多相关文章

  1. 【MOOC EXP】Linux内核分析实验二报告

    程涵  原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000  [操作系统是如何工作的]   教学内 ...

  2. 【MOOC EXP】Linux内核分析实验八报告

    程涵  原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 进程的切换和系统的一般执行过程 知识点 ...

  3. 【MOOC EXP】Linux内核分析实验七报告

    程涵  原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 可执行程序的装载 知识点梳理 一.预处 ...

  4. 【MOOC EXP】Linux内核分析实验六报告

    程涵  原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 进程的描述和进程的创建 知识点梳理: ...

  5. “Linux内核分析”实验一报告

    张文俊 + 原创作品转载请注明出处 + <Linux 内核分析> MOOC 课程 实验要求: 1.总结部分要求阐明自己对“计算机是如何工作的”理解: 2.博客中需要使用实验截图: 实验内容 ...

  6. “Linux内核分析”实验三报告

    构造一个简单的Linux系统 张文俊+原创作品转载请注明出处+<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-10000290 ...

  7. 【MOOC EXP】Linux内核分析实验四报告

    程涵  原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 [使用库函数API和C代码中嵌入汇编代 ...

  8. 【MOOC EXP】Linux内核分析实验一报告

    程涵  原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000  [反汇编一个简单的C程序]   实验 ...

  9. 【MOOC EXP】Linux内核分析实验三报告

     程涵  原创博客 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 [跟踪分析Linux内核的启动过程] ...

随机推荐

  1. kdTree相关原理及c++实现

    kdTree概念 kd-tree或者k维树是计算机科学中使用的一种数据结构,用来组织表示k维空间中点的集合.它是一种带有其他约束条件的二分查找树.Kd-tree对于区间和近邻搜索十分有用.一般位于三维 ...

  2. 【转】org.jdom.IllegalDataException: The data ""is not legal for a JDOM attribute: 0xb is not a legal 异常

    今天用jdom生成xml,在操作中出现了 org.jdom.IllegalDataException: The data ""is not legal for a JDOM att ...

  3. 13.1SolrCloud集群使用手册之Collections API

    转载请出自出处:http://www.cnblogs.com/hd3013779515/ 1.创建collection name:指明collection名字 router.name:指定路由策略,默 ...

  4. Spark学习之路 (二十二)SparkStreaming的官方文档

    官网地址:http://spark.apache.org/docs/latest/streaming-programming-guide.html 一.简介 1.1 概述 Spark Streamin ...

  5. 6、JVM--类文件结构(上)

    6.1.概述 写的程序需要经编译器翻译成由0和1构成的二进制格式才能由计算机执行 6.2.无关性基石 Java在刚刚诞生之时曾经提出过一个非常著名的宣传口号:“一次编写,到处运行(Write Once ...

  6. JAVA框架 Spring 注解注入

    一.首先需要引入jar包:spring-aop-4.2.4.RELEASE.jar.(在spring解压包libs内). 二.如果注解方式注入依赖的对象,需要引用新的约束. 内的:xsd-config ...

  7. Android Fragment(三)ListFragment简单介绍以及Fragment之间通信

    一.Fragment通信简单介绍:Fragments之间是不能够直接通信的,他们之间的通信是通过Activity这个中间件来通信的, 为了让Fragment跟它的Activity通信,我们可以在Fra ...

  8. JAVA程序员必看的15本书-JAVA自学书籍推荐

    作为Java程序员来说,最痛苦的事情莫过于可以选择的范围太广,可以读的书太多,往往容易无所适从.我想就我自己读过的技术书籍中挑选出来一些,按照学习的先后顺序,推荐给大家,特别是那些想不断提高自己技术水 ...

  9. mysql中left join中的on条件 和 where条件区别

    需要知道sql中关键字的执行顺序. FROM-> ON->JOIN-> WHERE->GROUP BY-> HAVING->SELECT-> DISTINCT ...

  10. 执行力:Just Do It

    执行力,最最关键的一点就是,立即去做,不要想太多. 当有一件事需要去做的时候,你的大脑肯定是接受到了"某种信号",比如来了一个灵感.受到一点启发.做某件事突然来了兴趣.或者想去探讨 ...