深入理解计算机操作系统(笔记)(代码片段)

逆水东流 逆水东流     2022-12-14     288

关键词:

深入理解计算机系统

1.实时系统概念
2.编译连接
3.AT&T汇编指令学习(GCC)
4.内存对齐
5.Big-Endian大端模式和Little-Endian小端模式
6.过程调用

1.实时系统概念

前后台系统

后台是各种面向硬件的程序,如中断,定时器,gpio等。
前台是:

main()


    while(1)
    
        ;
    

循环中不断调用各种函数实现功能。

代码临界段

指处理时不可分割的代码,一旦这部分代码运行就不可以打断、
为了确保代码能正常运行,进入临界段代码钱需要关中断,执行完后再开中断。

任务

一个任务也就是一个线程,是一个简单的程序。
任务间通信最简单的办法是使用数据共享结构。
任务间通信途径:1)全局变量;2)发消息给另一个任务。
任务切换(context switch)

基于优先级的内核

不可剥夺型内核,允许使用不可重入函数。
可剥夺型内核,,最高优先级的任务一就绪,总能得到CPU的使用权。,不能直接使用不可重入函数。

互斥条件

处理共享数据时保证互斥,最简单的办法是关中断和开中断。

信号量

一种约定机制。
就好像一把钥匙。任务要运行下去需要获得信号量,且信号量没有被占用。

死锁

两个任务相互等待对方释放资源。

同步

一个中断或者任务触发另一个任务。

邮箱

一种内存共享方式。

时钟节拍

特定的周期性中断,如同系统的心脏。

2.编译连接

目标文件的格式

可重定位文件:

包含代码和数据  
可被用来链接成执行文件或者共享目标文件  
linux(.o) windows(.obj)  

可执行文件:

包含可以执行的程序
系统可以直接执行的文件
linux (ELF文件,无后缀) windows (.exe)  

共享目标文件:

包含代码和数据
跟可重定位文件和共享目标文件链接,产生新的目标文件
动态连接器将共享目标文件与可执行文件结合,作为进程映像的一部分来运行
linux(.so) windows (.DLL)

核心转储文件

Linux(core dump)

目标文件的具体内容

file header

目标文件头

code section

程序指令(.code /.text)
存放程序代码程序

data section

程序数据(.data /.bss)
.data段 初始化的全局和局部静态变量
.bss段  未初始化的全局和局部静态变量
.bss(block started by symbol)符号预留块,没有内容不占据空间

othe section

还有可能包含的其他段,例 bank data .ect

程序指令和数据分开存放的优点?3点。

3.AT&T汇编指令学习(GCC)

  1. 寄存器命名原则:
    相比inter语法,AT&T语法格式要求所有的寄存器都必须加上取值符”%”.
  2. 操作码命令格式:

    1. 源/目的操作数顺序:
      Intel语法格式中命令表示格式为:”opcode dest, src”; “操作码 目标, 源”
      AT&T语法格式表示为:”opcode src, dest”; “操作码 源, 目标”

    2. 操作数长度标识:
      在AT&T语法中,通过在指令后添加后缀来指明该指令运算对象的尺寸.
      后缀 ‘b’ 指明运算对象是一个字节(byte)
      后缀 ‘w’ 指明运算对象是一个字(word)
      后缀 ‘l’ 指明运算对象是一个双字(long)
      Intel语法中指令’mov’在AT&T语法必须根据运算对象的实际情况写成:’movb’,’movw’或’movl’。
      注:若在AT&T中省略这些后缀,GAS将通过使用的寄存器大小来猜测指令的操作数长度.

    3. 另外,
      ‘FAR’不是GAS的关键字,因此对far的call或jmp指令须加前缀 ‘l’, ‘far call’要写成 ‘lcall’ , ‘far jmp’ 要写成 ‘ljmp’ , ‘ret far’ 写成 ‘lret’。
  3. 常数/立即数的格式:
    在AT&T语法中对立即数,须在其前加前缀 $ 来指明,而Inter语法则不需要。
    另外, 在常数前也必须加一个前缀字符 * ,而Inter语法则也是不需要的。
  4. 内存寻址方式:
    在Intel语法中,使用下面格式来表示存储器寻址方式:
    SECTION:[BASE + INDEX*SCALE + DISP];段:[基地址+变址*比例因子+偏移量]
    BASE是基地址索引寄存器(可以是任一通用寄存器),
    INDEX是变址寄存器(除ESP外的任一通用寄存器),
    SCALE是变址寄存器的比例常数,
    DISP是基址/变址寄存器的位移量。
    AT&T语法则使用不同的格式来表示寻址方式:
    SECTION:DISP(BASE, INDEX, SCALE);段:偏移量(基地址,变址,比例因子)
  5. 标号 & 标识符:
    所有的标号必须以一个字母,点或下划线开始,标号后加一个冒号表示标号的结束。
    局部标号使用数字0-9后跟一个冒号,使用局部标号时要在数字后跟一个字符’b’(向后引用)或字符’f’(向前引用)。因为只能使用数字0-9作为局部标号名,所以最多只能定义10个局部标号.一个标识符能给它赋于一个值。(如:’TRUE=1’, 或者使用 .set 或 .equ 指令)。
  6. 基本的行内汇编格式:
    asm("statements");
    例如:asm(“nop”); asm(“movl %eax,%ebx”);
    asm 和 _asm_是完全一样的.
    如果有多行汇编,则每一行都要加上 “\\n\\t”
  7. 扩展的行内汇编格式:
    asm ( "statements" : output_regs : input_regs : clobbered_regs);
    冒号后的语句指明输入,输出和被改变的寄存器.
  8. IA32整数寄存器:
  9. 常用指令:
    1. 数据传送指令:move,push,pop;
    2. 加载有效地址指令:leal;
    3. 一元操作指令:inc(加1),dec(减1),neg(取负),not(取补);
    4. 二元操作指令:add,sub,imul,idivl(有符号除法),xor,or,and;
    5. 移位指令:sal(左移),shl,sar(算数右移),shr(逻辑右移);
    6. 跳转指令:jmp,je,jne,js,jns,jg,jl,ja,jb,jbe…
  10. 条件码寄存器(单个bit):
    cf(进位标志),zf(零标志),sf(符号标志),of(溢出标志)…
    访问条件码指令:cmp,test,set…

    t = a + b;
    cf: (unsigned) t < (unsigned) a;//无符号溢出  
    zf: t == 0;//零  
    sf: t < 0;//负数  
    of: (a < 0 == b < 0) && (t < 0 != a < 0)//有符号溢出  
    

4.内存对齐

  1. 为何要内存对齐
    1. 平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
    2. 性能原因:经过内存对齐后,CPU的内存访问速度大大提升。
  2. 内存对齐的规则

    许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8)的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数(alignment modulus)。当一种类型S的对齐模数与另一种类型T的对齐模数的比值是大于1的整数,我们就称类型S的对齐要求比T强(严格),而称T比S弱(宽松)。这种强制的要求一来简化了处理器与内存之间传输系统的设计,二来可以提升读取数据的速度。

    比如这么一种处理器,它每次读写内存的时候都从某个8倍数的地址开始,一次读出或写入8个字节的数据,假如软件能保证double类型的数据都从8倍数地址开始,那么读或写一个double类型数据就只需要一次内存操作。否则,我们就可能需要两次内存操作才能完成这个动作,因为数据或许恰好横跨在两个符合对齐要求的8字节内存块上。某些处理器在数据不满足对齐要求的情况下可能会出错.

    但是Intel的IA32架构的处理器则不管数据是否对齐都能正确工作。不过Intel奉劝大家,如果想提升性能,那么所有的程序数据都应该尽可能地对齐。

    1. Win32平台下的微软C编译器(cl.exe for 80x86)在默认情况下采用如下的对齐规则:
      任何基本数据类型T的对齐模数就是T的大小,即sizeof(T)。比如对于double类型8字节),就要求该类型数据的地址总是8的倍数,而char类型数据(1字节)则可以从任何一个地址开始。
    2. Linux下的GCC对齐规则:
      char类型数据(1字节)起始位置任意,任何2字节大小的数据类型(比如short)的对齐模数是2,而其它所有超过2字节的数据类型(比如long,double)都以4为对齐模数。也就是说2字节数据类型(如short)的地址必须是2的倍数,而较大的数据类型(如int,double等)的地址必须是4的倍数,这意味着short类型的队形的地址最低位必须等于0,任何int类型的对象或指针的最低两位必须都是0.

5.Big-Endian大端模式和Little-Endian小端模式

定义

  1. Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
  2. Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
  3. 网络字节序:TCP/IP各层协议将字节序定义为Big-Endian,因此TCP/IP协议中使用的字节序通常称之为网络字节序.
  4. 高/低字节定义:在十进制中我们都说靠左边的是高位,靠右边的是低位,在其他进制也是如此。就拿 0x12345678来说,从高位到低位的字节依次是0x12、0x34、0x56和0x78.

例子分析:

unsigned int value = 0x12345678

1.Big-Endian: 低地址存放高位

  • 栈底 (高地址)
  • buf[3]
  • (0x78)
  • 低位
  • buf[2]
  • (0x56)
  • buf[1]
  • (0x34)
  • buf[0]
  • (0x12)
  • 高位
  • 栈顶 (低地址)

2.Little-Endian: 低地址存放低位

  • 栈底 (高地址)
  • buf[3]
  • (0x12)
  • 高位
  • buf[2]
  • (0x34)
  • buf[1]
  • (0x56)
  • buf[0]
  • (0x78)
  • 低位
  • 栈 顶 (低地址)

在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)

内存地址0x40000x40010x40020x4003
存放内容0x780x560x340x12

在Big- endian模式CPU内存中的存放方式则为

内存地址0x40000x40010x40020x4003
存放内容0x120x340x560x78

注意:通常我们说的主机序(Host Order)就是遵循Little-Endian规则。所以当两台主机之间要通过TCP/IP协议进行通信的时候就需要调用相应的函数进行主机序 (Little-Endian)和网络序(Big-Endian)的转换。
检查CPU是大端还是小端:

int checkCPU(void)  
  
    union  
      
        int a;  
        char b;  
    c;  
    c.a = 1;  
    return (c.b == 1);  

6.过程调用

1. 栈帧结构

说明:

返回值在相对%ebp偏移量为4的位置;
第一个参数放在相对于%ebp偏移量为8的位置;

支持过程调用和返回的指令:

一个过程调用的整个汇编流程示意:

《深入理解计算机系统》笔记(代码片段)

...黑皮书阅读笔记做主要内容,现在是看书的第一遍:导论操作系统的概念本章用于介绍本书的内容大致,其中若有概念不清楚,需要自己去网上搜集资料弄明白。信息和上下文不管什么文件终究被翻译为二进制文件供计算机执行... 查看详情

深入理解计算机系统笔记

二.存储器的层次结构 层次结构中较底层的设备访问时间较长,为了补偿这些较长的访问时间,倾向于使用较大的块。缓存不命中的种类:冷不命中(空的)冲突不命中(mod4)容量不命中2.  高速缓存确定一个缓存是... 查看详情

深入理解计算机系统(代码片段)

深入理解计算机系统卡内基·梅隆一门棵。原书第3版资料.第三版源码.原书第2版资料.计算机系统漫游源文件到目标文件的翻译过程可分为四个阶段,这四个阶段的程序被称为预处理器,编译器,汇编器和链接器,它们一起构成... 查看详情

深入理解计算机系统系列计算机系统漫游(代码片段)

操作系统原理是计算机行业基本功,想要成为一名计算机领域的专业人士,必不可少要打好基础。最近打算重点读一读《深入理解计算机系统》这本书,回顾和提升自己对计算机和操作系统的理解。这是第一篇:【计算机系统漫... 查看详情

《深入理解计算机系统》第三章学习笔记

通过本周的学习,总结出一下知识内容机器级代码计算机系统使用了多种不同形式的抽象,利用更简单的抽象模型来隐藏实现的细节。对于机器级编程来说,其中两种抽象尤为重要:1、指令集体系结构(InstructionsetarchitectureISA)... 查看详情

[阅读笔记]深入理解计算机系统

5、优化程序性能1.存储器别名(memoryaliasing),妨碍优化。__restrict关键字2.消除不必要的存储器引用,使用临时变量。6、存储器层次结构 1.寄存器0周期,cache1-10,主存50-100. 冷不命中coldmiss和冲突不命中conflictmiss。 2.cache结... 查看详情

读书笔记《深入理解计算机系统》(第三版)概述

  《深入理解计算机系统》第三版刚出来不到一周,便买下了这本书;之所以阅读本书,一方面源于网友推荐以及豆瓣不错的评分、评价;另一方面是针对本人非科班出身,计算机系统相关的知识相对比较薄弱,很多情况下此... 查看详情

深入理解计算机系统笔记

我的博客上的比这个排版显示的更好一些,特别是图片http://notelzg.github.io/2016/06/29/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%B3%BB%E7%BB%9F%E6%80%BB%E7%BB%93/1.hellowordl我们还是从helloworld程序说起吧:#includ 查看详情

《深入理解计算机系统》读书笔记

 第一部分概述综述本书从几个生动的计算机程序实例引入,带我们走进了一个庞大的计算机世界。计算机系统的诞生经历了无数个创新性时刻,每一个看似显然的成果都是来之不易的。比如,让计算机用一种我们能够理解的... 查看详情

深入理解计算机操作系统--读书笔记-第八章异常

该文章是我对深入理解计算机操作系统这本书的读书笔记异常概念:异常就是控制流的突变,用来响应处理器状态中的某些变化,当处理器状态发生变化时,处理器正在执行某个当前指令,在处理器中状态编码为不同的位和信号... 查看详情

《深入理解计算机系统》csapp_proxylab(代码片段)

ProxyLab开始日期:22.2.27操作系统:Ubuntu20.0.4Link:CS:APP3e目录ProxyLab写在前面实验环境bugfirefox网络代理配置需要提前理解的知识点参考链接partIpartIIpartIII总结写在前面实验环境bug在目录proxylab-handout中输入./driver.sh,出现bug:bug1:... 查看详情

深入理解计算机系统-读书笔记

第一章:计算机系统漫游编译过程:预处理阶段:预处理器根据字符#开头的命令,修改原始的c程序;编译阶段:编译器将ascii文本文件翻译成汇编语言程序;汇编阶段:汇编器将汇编语言程序翻译成机器指令,分为32位和64位系... 查看详情

读《深入理解计算机系统》chapter1(代码片段)

读《深入理解计算机系统》Chapter1基础很弱,来补一下。1.计算机中的信息表示形式我们知道计算机底层是有一堆集成电路元件组成,每个集成电路元件有很多个引脚,每个引脚同上直流电压之后只有0V/5V,所以每个只能表示两种... 查看详情

2018-2019-120189215《深入理解计算机系统》第一章(代码片段)

...算机存储设备的体系结构——金字塔层次结构。5.解释了操作系统、 查看详情

4.1《深入理解计算机系统》笔记链接知识附图

...   ●动态库(又叫共享库)的概念,一般用于操作系统,普通应用程序作用不大。   查看详情

3.2《深入理解计算机系统》笔记内存和高速缓存的原理插图

  《深入计算机系统》笔记(一)主要是讲解程序的构成、执行和控制。接下来就是运行了。我跳过了“处理器体系结构”和“优化程序性能”,这两章的笔记继续往后延迟!  《深入计算机系统》的一个很大的用... 查看详情

theartofmultipropcessorprogramming读书笔记-硬件基础1(代码片段)

...个人的资料硬件基础首先,我们无需掌握大量的底层计算机系统结构设计知识的细节,如果大家对于计算机系统结构非 查看详情

第1章计算机系统漫游(深入理解计算机系统)(代码片段)

1#include<stdio.h>23intmain()45printf("hello,world");61.1信息就是位+上下文hello程序的声明周期是从一个源程序开始的,即程序员利用编辑器创建并保存的文本文件,文件名是hello.c。源程序实际上就是一个由值0和1组成的位(bit)序列,... 查看详情