LINUX内核分析第二周学习总结——操作系统是如何工作的

张忻(原创作品转载请注明出处)

《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

一、知识点总结

(一)计算机是如何工作的?(总结)——三个法宝

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

  • 函数调用堆栈,高级语言得以运行的基础,只有机器语言和汇编语言的时候堆栈机制对于计算机来说并不那么重要,但有了高级语言及函数,堆栈成为了计算机的基础功能;

    • enter

      • pushl %ebp

      • movl %esp,%ebp

    • leave

      • movl %ebp,%esp

      • popl %ebp

    • 函数参数传递机制和局部变量存储

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

(二)函数调用堆栈

堆栈

1.堆栈是C语言程序运行时必须的一个记录调用路径和参数的空间。

2.堆栈存在的目的:函数调用框架;传递参数;保存返回地址;提供局部变量空间;等等。

3.C语言编译器对堆栈的使用有一套的规则。

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

堆栈寄存器和堆栈操作

1.堆栈相关的寄存器:esp,堆栈指针(stack pointer):ebp,基址指针(base pointer)

2.堆栈操作:push 栈顶地址减少4个字节(32位) pop 栈顶地址增加4个字节

3.ebp在C语言中用作记录当前函数调用基址

其他关键寄存器

cs : eip:总是指向下一条的指令地址

• 顺序执行:总是指向地址连续的下一条指令

• 跳转/分支:执行这样的指令的时候,cs : eip的值会 根据程序需要被修改

• call:将当前cs : eip的值压入栈顶,cs : eip指向被 调用函数的入口地址

• ret:从栈顶弹出原来保存在这里的cs : eip的值,放 入cs : eip中

• 发生中断时

举例分析函数调用堆栈

(三)借助Linux内核部分源代码模拟存储程序计算机工作模型及时钟中断

(四)在mykernel基础上构造一个简单的操作系统内核

C语言中代码嵌入汇编代码的方法

二、作业

1.实验

中断:CPU和内核代码共同实现了保存现场和恢复现场。

mypcb.h

有效esp ebp

typedef struct PCB{

...

...

进程用链表链接起来

}

mymain.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 = ; /*
* 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% == && my_need_sched != )
{
printk(KERN_NOTICE ">>>my_timer_handler here<<<\n");
my_need_sched = ;
}
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 == )/* -1 unrunnable, 0 runnable, >0 stopped */
{
/* switch to next process */
asm volatile(
"pushl %%ebp\n\t" /* save ebp */保存当前进程的ebp
"movl %%esp,%0\n\t" /* save esp */把当前进程的esp赋给%0(指的是thread.sp),即保存当前进程的esp
"movl %2,%%esp\n\t" /* restore esp */把%2(指下一个进程的sp)放入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 = ;
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;
}

视频中的详细分析:

 #include <asm/io.h>
#include <asm/bugs.h>
#include <asm/setup.h>
#include <asm/sections.h>
#include <asm/cacheflush.h> #ifdef CONFIG_X86_LOCAL_APIC
#include <asm/smp.h>
#endif
//之前为初始化 从这里开始是操作系统的入口
void __init my_start_kernel(void)
{
int i = ;
while()
{
i++;
if(i% == )
printk(KERN_NOTICE "my_start_kernel here %d \n",i); }
}

每循环十万次打印一个。

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 = ; /*
* 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% == && my_need_sched != )
{
printk(KERN_NOTICE ">>>my_timer_handler here<<<\n");
my_need_sched = ;
}
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 == )/* -1 unrunnable, 0 runnable, >0 stopped */
{
/* switch to next process */
如果下一个进程的状态是正在执行的话,就运用if语句中的代码表示的方法来切换进程
asm volatile(
"pushl %%ebp\n\t" /* save ebp */保存当前进程的ebp
"movl %%esp,%0\n\t" /* save esp */把当前进程的esp赋给%0(指的是thread.sp),即保存当前进程的esp
"movl %2,%%esp\n\t" /* restore esp */ 把%2(指下一个进程的sp)放入esp中
"movl $1f,%1\n\t" /* save eip */ 是接下来的标号“1:”的位置,把eip保存下来
"pushl %3\n\t" 把下一个进程eip压栈
"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 = ;
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;
}

视频中的详细分析:

 #include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/div64.h>
#include <asm/timex.h>
#include <asm/io.h> #define CREATE_TRACE_POINTS
#include <trace/events/timer.h> /*
* Called by timer interrupt.
*/
void my_timer_handler(void)
{
printk(KERN_NOTICE "\n>>>>>>>>>>>>>>>>>my_timer_handler here<<<<<<<<<<<<<<<<<<\n\n");
}

每次时钟中断都调用一次printk()

2.总结:操作系统是如何工作的

(1)工作的基础:存储程序计算机、堆栈机制、中断机制

(2)操作系统内核是如何工作的

进程是动态执行的实体,内核是进程的管理者。进程不但包括程序的指令和数据,而且包括程序计数器和CPU的所有寄存器以及存储临时数据的进程堆栈。所以,正在执行的进程包括处理器当前的一切活动。进程既可以在用户态下运行,也能在内核下运行,只是内核提供了一些用户态没有的核心服务,因此进程在访问这些服务时会产生中断,必须进行用户态与内核态的切换。

Linux是一个多进程的操作系统,所以,其他的进程必须等到正在运行的进程空闲CPU后才能运行。当正在运行的进程等待其他的系统资源时,Linux内核将取得CPU的控制权,并将CPU分配给其他正在等待的进程,这就是进程切换。内核中的调度算法决定将CPU分配给哪一个进程。

Linux系统有一个进程控制表(process table),一个进程就是其中的一项。进程控制表中的每一项都是一个task_struct结构,在task_struct结构中存储各种低级和高级的信息,包括从一些硬件设备的寄存器拷贝到进程的工作目录的链接点。进程控制表既是一个数组,又是一个双向链表,同时又是一个树,其物理实现是一个包括多个指针的静态数组。系统启动后,内核通常作为某一个进程的代表。一个指向task_struct的全局指针变量current用来记录正在运行的进程。

参考资料:http://blog.chinaunix.net/uid-28281877-id-3778550.html

LINUX内核分析第二周学习总结——操作系统是如何工作的的更多相关文章

  1. Linux内核分析第二周学习博客——完成一个简单的时间片轮转多道程序内核代码

    Linux内核分析第二周学习博客 本周,通过实现一个简单的操作系统内核,我大致了解了操作系统运行的过程. 实验主要步骤如下: 代码分析: void my_process(void) { int i = ...

  2. Linux内核分析第二周学习笔记

    linux内核分析第二周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...

  3. LINUX内核分析第一周学习总结——计算机是如何工作的

    LINUX内核分析第一周学习总结——计算机是如何工作的 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/course/ ...

  4. Linux内核分析第二周学习总结:操作系统是如何工作的?

    韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.函数调用堆栈 ...

  5. 三20135320赵瀚青LINUX内核分析第二周学习笔记

    赵瀚青原创作品转载请注明出处<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.计算机的三个法宝 存储程 ...

  6. Linux内核分析——第二周学习笔记

    20135313吴子怡.北京电子科技学院 chapter 1 知识点梳理 (一)计算机是如何工作的?(总结)——三个法宝 ①存储程序计算机工作模型,计算机系统最最基础性的逻辑结构: ②函数调用堆栈,高 ...

  7. Linux内核分析——第二周学习笔记20135308

    第二周 操作系统是如何工作的 第一节 函数调用堆栈 存储程序计算机:是所有计算机基础的框架 堆栈:计算机中基础的部分,在计算机只有机器语言.汇编语言时,就有了堆栈.堆栈机制是高级语言可以运行的基础. ...

  8. 20135302魏静静Linux内核分析第二周学习总结

    操作系统是如何工作的 1. 小结:计算机是怎样工作的 三个法宝 存储程序计算机.函数调用堆栈.中断机制 两把宝剑 中断上下文.进程上下文的切换 2. 堆栈 堆栈是C语言程序运行时必须的一个记录调用路径 ...

  9. Linux内核分析第二周--操作系统是如何工作的

    Linux内核分析第二周--操作系统是如何工作的 李雪琦 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course ...

随机推荐

  1. Beta阶段第一次冲刺

    Beta阶段第一次冲刺 以后严格按照Git标准来,组员有上传Git的才有贡献分没有的为0 代码签入图 1.part1 -站立式会议照片 2.part2 -项目燃尽图 3.part3 -项目进展 1.正 ...

  2. 团队-UML

    UML设计 分工 刘双玉 李佳铭 杜宏庆 肖小强 汪志彬 江郑 符天愉 邓弘立 后台数据库 求购模块 浏览检索商品 即时聊天系统 商品管理 管理员系统 后台商品发布收藏系统 登录注册与个人信息系统 U ...

  3. .Net Core Api 跨域配置

    .Net Core 和Asp.Net 不同,不需要再去引用其他的跨域组件.创建项目时,就有了. 让接口实现跨域,需要配置两个地方. 一.Startup.cs 这里需要配置两个地方 public voi ...

  4. [BUG] python实例化N次类,调用类函数log会输出N遍的bug 解决办法

    最近再写DOU用例时,采用的是 unittest测试框架,就涉及到将其它所有模块需要全部在一个 .py文件中进行实例化,然后再运行时发现在控制台中同一个日志信息会打印多次(实例化几次,同一消息就会打印 ...

  5. 动态显示checkbox选中条数

    <script> $('input[type=checkbox]').click( function () { $('span#cheak_len').empty(); var len = ...

  6. css3动画功能介绍

    一:过渡动画---Transitions 含义:在css3中,Transitions功能通过将元素的某个属性从一个属性值在指定的时间内平滑过渡到另一个属性值来实现动画功能. Transitions属性 ...

  7. #HTTP协议学习# (一)request 和response 解析

    注:本文转自:http://www.cnblogs.com/TankXiao/archive/2012/02/13/2342672.html , 粉字[]内内容为个人笔记 当今web程序的开发技术真是 ...

  8. DRUPAL7 : 安装中文版本时遇到的问题

    http://yeenav.com是基于Drupal 7+汉化资源 搭建. 期间遇到一些麻烦, 做个记录. 首先把语言包drupal-7.0.zh-hans.po 放在htdocs/drupal-7. ...

  9. [HAOI2008]排名系统 & [Zjoi2006]GameZ游戏排名系统 BZOJ1862&BZOJ1056

    分析: 平衡树裸题,(学完LCT感觉自己不会普通的Splay了...),维护每个节点的权值大小顺序,和时间戳顺序,之后map维护一下是否存在过,(懒得写字符串hash了). 附上代码: #includ ...

  10. Linux日记Day3---Linux的文件属性与目录配置

    Linux最优秀的地方之一,就在于它的多用户.多任务环境.为了让用户具有较安全的管理机制,文件的权限管理是很重要的.Linux通常将文件的访问方式分为分为三个类别,分别是owner/group/oth ...