操作系统是如何工作的

1. 小结:计算机是怎样工作的

三个法宝

存储程序计算机、函数调用堆栈、中断机制

两把宝剑

中断上下文、进程上下文的切换

2. 堆栈

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

    • 函数条用框架
    • 传递参数
    • 保存返回地址
    • 提供局部变量空间...
  • 堆栈相关寄存器:

    esp:堆栈指针——指向系统栈最上面一个栈帧的栈顶
    ebp: 基址指针——指向系统栈最上面一个栈帧的底部
    cs:eip:指令寄存器——指向下一条等待执行的指令地址
  • 堆栈相关操作:
    • push :栈顶地址减少4个字节
    • pop: 栈顶地址增加4个字节
    • call:将当前cs:eip值压栈,cs:eip指向被调函数入口地址。
    • ret:从栈顶弹出原来保存在此的cs:eip值,放入cs:eip中。
    • leave:当调用函数调用时,一般都有这两条指令pushl %ebpmovl %esp,%ebp,leave是这两条指令的反操作。

3. 函数调用约定

函数调用约定 参数传递顺序 负责清理参数占用的堆栈
__pascal 从左到右 调用者
__stdcall 从右到左 被调函数
__cdecl 从右到左 调用者
      • 调用函数的代码和被调函数必须采用相同的函数的调用约定,程序才能正常运行。

        Windows中C/C++程序的缺省函数调用约定是__cdecl
        linux中gcc默认用的规则是__stdcall

4、C代码中嵌入汇编代码的写法

__asm__(汇编语句模板: 输出部分: 输入部分: 破坏描述部分)
  • 汇编语句模板
       汇编语句模板由汇编语句序列组成,语句之间使用“;”、“\n”或“\n\t”分开。指令中的操作数可以使用占位符引用C语言变量,操作数占位符最多10个,名称如下:%0,%1,…,%9。
  • 输出部分
       输出部分描述输出操作数,不同的操作数描述符之间用逗号格开,每个操作数描述符由限定字符串和C语言变量组成。
  • 输入部分
       输入部分描述输入操作数,不同的操作数描述符之间使用逗号格开,每个操作数描述符由限定字符串和C语言表达式或者C语言变量组成。
  • 破坏描述部分
       破坏描述符用于通知编译器我们使用了哪些寄存器或内存,由逗号格开的字符串组成,每个字符串描述一种情况,一般是寄存器名;除寄存器外还有“memory”。
  • 限制字符
       限制字符有很多种,有些是与特定体系结构相关,它们的作用是指示编译器如何处理其后的C语言变量与指令操作数之间的关系。 
常用限制字符
分类 限定符 描述
通用寄存器 “a” 将输入变量放入eax
“b” 将输入变量放入ebx
“c” 将输入变量放入ecx
“d” 将输入变量放入edx
“s” 将输入变量放入esi
“d” 将输入变量放入edi
“q” 将输入变量放入eax,ebx,ecx,edx中的一个
“r” 将输入变量放入通用寄存器,也就是eax,ebx,ecx,edx,esi,edi中的一个
“A” 把eax和edx合成一个64 位的寄存器(use long longs)
内存 “m” 内存变量
“o” 操作数为内存变量,但是其寻址方式是偏移量类型,也即是基址寻址,或者是基址加变址寻址
“V” 操作数为内存变量,但寻址方式不是偏移量类型
“ ” 操作数为内存变量,但寻址方式为自动增量
“p” 操作数是一个合法的内存地址(指针)
寄存器或内存 “g” 将输入变量放入eax,ebx,ecx,edx中的一个或者作为内存变量
“X” 操作数可以是任何类型
立即数 “I” 0-31之间的立即数(用于32位移位指令)
“J” 0-63之间的立即数(用于64位移位指令)
“N” 0-255之间的立即数(用于out指令)
“n” 立即数
“p” 立即数,有些系统不支持除字以外的立即数,这些系统应该使用“n”而不是“i”
匹配 & 该输出操作数不能使用过和输入操作数相同的寄存器
操作数类型 “=” 操作数在指令中是只写的(输出操作数)
“+” 操作数在指令中是读写类型的(输入输出操作数)
浮点数 “f” 浮点寄存器
“t” 第一个浮点寄存器
“u” 第二个浮点寄存器
“G” 标准的80387浮点常数
其它 % 该操作数可以和下一个操作数交换位置
# 部分注释,从该字符到其后的逗号之间所有字母被忽略
* 表示如果选用寄存器,则其后的字母被忽略

5.mykernel实验

  1. cd LinuxKernel/linux-3.9.4
  2. qemu -kernel arch/x86/boot/bzImage

然后cd mykernel 可以看到qemu窗口输出的内容的代码mymain.c和myinterrupt.c

  • 进程的启动
/*mymain.c*/
/* start process 0 by task[0] */
pid = 0;
my_current_task = &task[pid];
asm volatile(
"movl %1,%%esp\n\t" /* 将进程的sp赋给esp寄存器 */
"pushl %1\n\t" /* ebp入栈:因为在这里栈为空,esp=ebp,所以push的%1就是esp就是ebp。*/
"pushl %0\n\t" /* 进程入口ip入栈 */
"ret\n\t" /* 把进程入口ip赋给eip,即从这之后0号进程启动。*/
"popl %%ebp\n\t"
:
: "c" (task[pid].thread.ip),"d" (task[pid].thread.sp) /* input c or d mean %ecx/%edx*/
);
  • 进程的切换:
(1).下一个进程next->state == 0 即正在执行时
/*myinterrupt.c*/
//两个正在运行的进程之间做进程上下文切换 if(next->state == 0)
/* state值的含义:-1表示没有执行,0表示正在执行,>0表示停止,这里为0,即进程正在执行 */
{
/* 以下是进程切换关键代码 */
asm volatile(
"pushl %%ebp\n\t" /* 把当前进程的ebp保存*/
"movl %%esp,%0\n\t" /* 把当前进程的esp赋值到sp中保存下来*/
"movl %2,%%esp\n\t" /* 把下一个进程的sp放到esp中*/
"movl $1f,%1\n\t" /* 把eip保存起来,$1f指接下来的标号1:的位置*/
"pushl %3\n\t" /*把下一个进程的eip保存起来*/
"ret\n\t" /* 还原eip */
"1:\t" /* 标号1,下一进程从此开始 */
"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);
}
(2).进程是一个新进程,还从未执行过
/*myinterrupt.c*/
/*这段代码是当进程从未执行过时,所执行的动作,即启动一个进程 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" /* 保存ebp */
"movl %%esp,%0\n\t" /* 保存esp */
"movl %2,%%esp\n\t" /* 将下一进程的sp存入esp */
"movl %2,%%ebp\n\t" /* 将下一进程的bp存入ebp,因为栈空,所以esp和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)
);
  • 实验截图

20135302魏静静Linux内核分析第二周学习总结的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. linux内核分析第二周

    网易云课堂linux内核分析第二周 20135103                王海宁 <Linux内核分析>MOOC课程http://mooc.study.163.com/cours ...

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

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

随机推荐

  1. 04.Curator Leader选举

        在分布式计算中,leader election是很重要的一个功能,这个选举过程是这样子的:指派一个进程作为组织者,将任务分发给各节点.在任务开始前,哪个节点都不知道谁是leader或者coor ...

  2. 170317、到底什么时候该使用MQ?

    一.缘起 一切脱离业务的架构设计与新技术引入都是耍流氓. 引入一个技术之前,首先应该解答的问题是,这个技术解决什么问题. 就像微服务分层架构之前,应该首先回答,为什么要引入微服务,微服务究竟解决什么问 ...

  3. 160519、Oracle中将查询出的多条记录的某个字段拼接成一个字符串的方法

    with temp as( select 'China' nation ,'Guangzhou' city from dual union all select 'China' nation ,'Sh ...

  4. application/x-protobuf payload加密 知乎

  5. linux 命令行 执行 php

    w为监控响应功能做准备. ubuntu@VM-52-248-ubuntu:~$ php -f /var/www/html/wlinux.phpwwubuntu@VM-52-248-ubuntu:~$ ...

  6. jsp->jar

    (2)新建 WEB-INF目录 (3)在 WEB-INF/web.xml 中输入如下内容 <web-app xmlns="http://java.sun.com/xml/ns/j2ee ...

  7. FW:主流RPC框架

    主流RPC框架  2015年10月27日  zman  RPC 介绍目前在互联网公司比较流行的开源的RPC框架. RPC框架比较   语言 协议 ​服务治理 ​社区 机构 Hessian 多语言 he ...

  8. Laravel 5.x HTTPS反向代理的实现

    需求 可针对多个域名设置HTTPS并指向到同一个项目. 最先考虑到的是通过nginx的反向代理来实现,最终测试发现效果并不完美. 示例如下: server { listen 127.0.0.1:808 ...

  9. 【python】-- RabbitMQ 队列消息持久化、消息公平分发

    RabbitMQ 队列消息持久化 假如消息队列test里面还有消息等待消费者(consumers)去接收,但是这个时候服务器端宕机了,这个时候消息是否还在? 1.队列消息非持久化 服务端(produc ...

  10. php 验证上传图片尺寸

    getimagesize 函数 取得图像大小 (PHP 4, PHP 5) array getimagesize ( string filename [, array &imageinfo] ...