Menu

  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay
  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay

操作系统知识集锦

11
May
2010

操作系统知识集锦

By Alex
/ in Linux,OS,Windows
0 Comments
硬件平台基础知识
总线

在计算机领域,总线(来源于拉丁语omnibus)是用于在计算机内部组件之间进行数据传输的通信子系统。总线上传递的数据类型包括数据信息、地址信息、控制信息。

在个人计算机上,总线一般分为5类:

  1. 数据总线(Data Bus):在CPU与RAM或其它设备之间来回传送需要处理或是需要储存的数据。数据总线的宽度决定了CPU与外界数据交换的最大速率。数据总线有一系列的传输线组成,每条传输线同一时刻只能传输1bit的数据,如果数据总线位宽为64位,就意味着有64根传输线
  2. 地址总线(Address Bus):CPU通过地址总线来指定存储器的地址,地址总线决定了CPU能访问的最大内存空间大小
  3. 控制总线(Control Bus):将处理器控制单元(Control Unit)的信号传送到周边设备,一般常见的为USB总线
  4. 扩展总线(Expansion Bus):可连接扩展槽,以增添设备
  5. 局部总线(Local Bus):直接的连接CPU与部分扩展总线的插槽,避免扩展总线引入的性能瓶颈,提高数据吞吐量

 在Intel的处理器产品线中,总线还可以按如下方式分类:

  1. 系统总线:一般特指PCI/PCIe总线,带宽高,支持热插拔。内部总线、外部总线都挂接在系统总线上
  2. 外部总线:诸如USB、SATA、IDE、1394、以太网等暴露在外的,都属于外部总线
  3. 内部总线:外部总线上的一些零散小芯片使用
  4. 前端总线:CPU与北桥、内存的连接总线,北桥是PCI/PCIe的发源地
频率

CPU时钟频率速度(主频)=系统总线速率(外频)×倍频系数,某些主板可以通过跳线设置倍频系数、系统总线频率。

在早期,并没有倍频这一概念,CPU主频与外频是一致的。然而CPU的速率越来越快,开始出现倍频——让CPU主频与总线频率之间呈现倍数关系,这样CPU可以高速运作,而外设以低频运作。

在早期,系统总线、前端总线的工作频率也是一致的,目前前端总线往往是系统总线的数倍速度。

SMP

CPU设计初期是往高频率方向发展的,然而最终遭遇到物理极限的限制。这时为了继续提高处理能力,只能向多核心、多CPU的方向发展了。

CPU有多个,而内存是大家共享的,这时SMP架构出现了。所谓对称多处理(Symmetric multiprocessing,SMP)是指每个处理器核心的地位都是平等的(所谓对称),对所有计算机资源(特别是内存)具有相同的使用权限。

SMP的优点是并行度高,然而系统总线的带宽有限,因此处理器的数目不能无限添加,系统性能和处理器数量也不是线性关系。

Linux对SMP的早期支持依赖于一个全局大锁,直到2.6才有效的发挥SMP的能力。

NUMA

SMP的最大问题在于总线带宽有限,当很多CPU都通过北桥来读写内存,北桥带宽的瓶颈很快就出现了。

为了解决此问题,硬件工程师开始把北桥中的内存控制器拆分,让CPU与特定内存插槽、内存控制器关联在一起。当CPU访问自己本地内存(Local Access)时,速度很快,而需要访问其它CPU的内存(Remote Access)时速度就慢了。这就是所谓非统一内存访问(Non-Uniform Memory Access,NUMA)的由来。

NUMA一定程度上保证了单台主机的扩容能力,然而操作系统面临的问题则是,如何尽可能的避免Remote Access。Linux的默认策略是:

  1. 优先尝试在请求线程当前所处的CPU的本地内存中进行分配
  2. 如果本地内存不足,尝试淘汰(Reclaim)其中无用的页
PCI

外设组件互连标准(Peripheral Component Interconnect),是一种连接电脑主板和外部设备的总线标准。基于PCI标准连接到主板的外设,要么嵌入到主板的集成电路中,要么通过主板上的PCI插槽连接。

目前PCI总线已经被更先进的技术,例如PCI Express(PCIe)逐步取代。

PCI子系统包含四级模块:

  1. Bus,一个PCI子系统最多256个Bus,常用的是Bus 0和Bus 1
  2. Device,即连接到Bus上的设备,如声卡,网卡等,每个Bus最多32个
  3. Function,每个Device有至少有一个Function 0,最多8个
  4. Register,每个Function有256字节的的Registers
SCSI

SCSI是一种用于计算机和智能设备之间(硬盘、软驱、光驱、打印机、扫描仪等)系统级接口的独立处理器标准。与IDE最大的不同是,IDE的工作需要CPU全程参与,而SCSI卡自带处理器,因而CPU占用极低。

iSCSI

集因特网小型计算机系统接口(Internet Small Computer System Interface),又称为IP-SAN,是一种基于Internet和SCSI-3协议下的存储技术,与传统的SCSI相比,其优势为:

  1. 将原先仅用于单机的SCSI协议通过TCP/IP网络传输
  2. 连接的服务器数量没有限制,而SCSI-3有15的限制

iSCSI让计算机可以透过高速的局域网来把SAN模拟成为本地的储存装置。它让两个主机通过 IP 网络相互协商然后交换 SCSI 命令,用局域网仿真了高性能本地存储总线。与某些SAN协议不同,iSCSI 不需要专用的电缆,被认为是光纤通道(Fiber Channel)的一个低成本替代方法。

指令集架构(Instruction Set Architecture,ISA)

亦称指令集,是计算机体系结构(Computer Architecture)中与编程相关的部分,其包括了:基本(native)数据类型、指令、寄存器、寻址模式、内存架构、中断、异常处理、外部I/O几个方面的内容。指令集包括了一系列面向机器语言的操作码(Opcodes),这些操作码由特定的CPU实现。

复杂指令集计算机(CISC)、精简指令集计算机(RISC)是根据指令集的复杂度来区分的,前者包含很多不常使用的指令,并且导致指令长度不固定。大部分RISC具有固定的指令长度,通常与机器字一样长。

每条指令由一个Opcode、0个或者多个算子组成,这些算子可能是寄存器编号、内存位置或者字面值。

从功能上,指令可以分为以下几种类型:

  1. 数据读写操作指令:设置寄存器的值、读取寄存器的值、取出数据并计算、保存计算结果、从硬件读写数据
  2. 算术与逻辑运算指令:对两个寄存器中的值进行加减乘除、执行位操作、执行逻辑与、逻辑非、逻辑或、比较两个寄存器中数据的大小
  3. 控制流指令:分支——跳跃到某个地址继续执行、条件分支、间接分支——跳跃前,将下一条指令的位置存储起来,作为子程序的返回地址

 注意术语“微架构”与指令集架构没有直接关系,前者代表了一种处理器硬件的设计方式,不同微架构的处理器可以实现同一套指令集。

x86指令集架构家族

x86包含了一系列指令集架构,它们都是可变指令长度的CISC,最早由英特尔在1978年面市的“Intel 8086”CPU上开发出来。三年后IBM PC开始使用8086,x86逐渐成为个人计算机的标准平台。

x86这个名称的由来是Intel早期CPU的名称:Intel 8086、80186、80286、80386、80486,后续的处理器由于商标的问题,改用“Pentium”之类的名称。现在Intel把x86-32称为IA-32,尽管x86系列包含16位处理器。与IA-32对应的是IA-64,这是早在1990年代就提出的,在安腾系列处理器中使用的独立64位架构,与IA-32完全不兼容。

除了Intel以外,还有若干厂商实现了x86指令集的CPU,其中包括AMD的Athlon系列处理器。有趣的是,2003年,AMD发布了针对x86架构的64位扩充,命名为AMD64,Intel则被迫推出了与AMD64兼容的CPU,并命名为Intel 64。不同操作系统厂商对AMD64使用不同的称呼:Apple称之为x86-64或者x86_64;Sun和微软称之为x64;BSD和Linux称之为amd64,并把32位版本成为i386。

字

在计算机领域,“字(Word)”是用于表示其自然的数据单位的术语,对应了CPU一次性处理事务的固定比特位宽度。字在多个方面有体现,例如大部分通用寄存器的尺寸是一个字长;CPU与内存之间数据传输的单位也是字长;内存地址也通常用字长来表示。

为了保证向后兼容,实际的体系结构下经常把字固定为某个长度,以Intel为例,由于后续的处理器都是对8086的扩充,所以IA-32、AMD64架构下,字一直保持16位的大小,对VC的数据类型WORD、DWORD执行sizeof可以明确的看到这一点。

64位元

64位、32位是人们经常提到的名词,但是所谓64位到底指的是什么?如果一颗处理器是64位的,通常是指:

  1. 该CPU的各种指针寄存器是64位的,因此理论上支持16EB的存储器
  2. 该CPU的通用寄存器是64位的,因此支持64位二进制整数的直接算术与逻辑运算
  3. 该CPU具有64位宽的地址、数据总线

现实的情况比较复杂,由于硬件设计、操作系统限制,64位机支持的存储器大小远远小于16EB,地址总线的宽度也往往没有64位。

AMD64(x86_64)

可以认为是x86指令集的64位版本。AMD64理论上支持2^64比特(16EB)的寻址空间,并引入了若干64位通用寄存器和其它的特性增强。由于AMD64保留了全部16位、32位x86指令,因此它完全向后兼容(Backwards Compatible )16位、32位的x86代码。首片支持AMD64的CPU是2003年发布的AMD Opteron。

AMD64具有以下特性:

64位整数支持

所有的通用寄存器被从32位扩充到64位,因此所有的64位算术、逻辑、寄存器-内存操作可以直接在64位整数上操作;压栈/弹出操作默认8字节步长;指针默认8字节宽。

引入额外的寄存器

除了扩展通用寄存器的长度外,其数量也被加倍,从8扩展到16,因此,可以在寄存器上存放更多的局部变量,而避免存放在栈上。

128位SSE寄存器的数量也从8增加到16。

更大的虚拟地址空间

AMD64定义了64位的虚拟地址格式,理论上最大支持16EB的地址空间,目前只使用了其中的低48位,因此支持256TB的虚拟地址空间。

更大的物理地址空间集锦

AMD64的初始版本允许40位的物理地址,因此最大支持1TB的物理内存。当前版本的实现则使用48位物理地址,可以支持256TB的物理内存。由于页表条目结构的限制,未来最多可以扩展到52位物理地址。

当AMD64在遗留模式(实模式、保护模式)下运行时,PAE由36位扩展到52位,因此物理地址的限制与长模式一致。相比之下,32位的x86处理器在物理地址扩展(PAE)模式下最多支持64GB的物理内存,不使用PAE则最多4GB内存。

IP相对数据访问

在AMD64架构下,允许根据当前指令指针(RIP)来访问相对位置的数据,可以实现位置无关代码(Position Independent Code),这在共享库、动态加载代码中更加高效。

禁止执行比特位

NX位是页表的最高位,允许操作系统指定哪些虚拟地址空间的页可以包含executable代码,哪些不能。尝试执行NX页的代码,会导致内存访问违例(Memory Access Violation)。

x86运作模式
 运作模式 说明 
实模式

即“真实地址模式”,是8086即以后的x86兼容CPU的一种运作模式。其特征是逻辑地址直接指向物理地址。实模式包含20位的分段的地址空间(仅仅1MB地址空间),必须将段地址左移4位,然后加上地址偏移量才能得到最终的20位地址。

实模式支持通过软件直接访问硬件、没有硬件级别的内存保护、多任务的概念。

80286以及以后的CPU在启动后首先处于实模式,80186只有一种运作模式,类似于实模式。

 

操作系统要求:16位实模式操作系统或者16/32/64位启动加载器(Boot Loader)
指向代码类型:16位实模式代码
默认地址尺寸:16位
默认操作数尺寸:16位
支持的典型操作数尺寸:8/16/32
寄存器堆尺寸:8寄存器
通用寄存器典型宽度:16/32

保护模式

所谓保护模式,即“受保护的虚拟地址模式”,x86兼容机器不会直接进入保护模式,必须在操作系统设置好若干描述符表(GDT等)后,并且设置了控制寄存器(CR0)的PE位(Protection Enable)后才能生效。保护模式具有以下特性:

  1. 特权级别(Privilege levels,aka rings),用数字0-3表示 ,0的级别最高,大部分操作系统代码和驱动程序工作在0级别,应用程序则工作在3级别。特权级别用于限制数据访问、限制执行特定的指令
  2. 支持虚拟内存( virtual memory)
  3. 支持安全的多任务(multi-tasking)设计。80286引入了任务状态段(TSS),配合特权级别机制可以实现安全的多任务
  4. 80386引入到保护模式的新特性:32bit物理和虚拟地址空间、分页(paging)、32位的段偏移量、不需要重启的返回实模式、虚拟8086模式

保护模式(16位)最初由80286引入,将可寻址的物理内存扩充到16MB,可寻址的虚拟内存最大到1GB。

16位保护模式相关参数:

操作系统要求:16位保护模式操作系统或者16/32/64位启动加载器
指向代码类型:16位保护模式代码
默认地址尺寸:16位
默认操作数尺寸:16位
支持的典型操作数尺寸:8/16/32
寄存器堆尺寸:8寄存器
通用寄存器典型宽度:16/32

 

32位保护模式相关参数:

操作系统要求:32位保护模式操作系统或者32/64位启动加载器
指向代码类型:32位保护模式代码
默认地址尺寸:32位
默认操作数尺寸:16位
支持的典型操作数尺寸:8/16/32
寄存器堆尺寸:8寄存器
通用寄存器典型宽度:32

虚拟8086模式

用于支持先前基于8086的程序不经修改的运行在80386下,支持与其它任务并发运行

 

操作系统要求:16/32位保护模式操作系统
指向代码类型:16位实模式代码
默认地址尺寸:16位
默认操作数尺寸:16位
支持的典型操作数尺寸:8/16/32
寄存器堆尺寸:8寄存器
通用寄存器典型宽度:16/32

长模式

在x86_84架构处理器中,长模式(Long mode)允许64位操作系统或者应用程序使用64位指令和寄存器,而32位、16位程序则以一种兼容子模式来运行。

不在长模式下(兼容模式)运行时,x86_64处理器与x86_32处理器的行为完全相同

 

16位兼容模式相关参数:

操作系统要求:64位保护模式操作系统
指向代码类型:16位保护模式代码
默认地址尺寸:16位
默认操作数尺寸:16位
支持的典型操作数尺寸:8/16/32
寄存器堆尺寸:8寄存器
通用寄存器典型宽度:32

32位兼容模式相关参数:

操作系统要求:64位保护模式操作系统或者64位启动加载器
指向代码类型:32位保护模式代码
默认地址尺寸:32位
默认操作数尺寸:32位
支持的典型操作数尺寸:8/16/32
寄存器堆尺寸:8寄存器
通用寄存器典型宽度:32

长模式相关参数:

操作系统要求:64位保护模式操作系统或者64位启动加载器
指向代码类型:64位代码
默认地址尺寸:64位
默认操作数尺寸:32位
支持的典型操作数尺寸:8/16/32/64
寄存器堆尺寸:16寄存器
通用寄存器典型宽度:64

虚拟内存(Virtual memory)

这里所说的虚拟内存与Windows面向用户的“虚拟内存是两回事”,后者实际上是分页技术(Paging)。

操作系统将大小一致的、代表连续虚拟地址空间的数据块称为“页(Page)”;相应的,物理地址空间上与页大小一致的连续空间则被称为“页帧(Page Frame)”。32位x86处理器的内存管理单元(MMU,CPU中的特殊硬件)支持从4KB到4MB大小的页。

虚拟内存是同时使用硬件、软件实现的一种内存管理技术。它将应用程序使用的内存地址(即虚拟地址,Virtual Addresses)映射到计算机内存(即主存,Main Storage)的物理地址(Physical Addresses)。在应用程序看来,内存是一个连续的地址空间,实际上则可能是分散在物理内存上的多个片段。

虚拟地址与物理地址的映射(即页与页帧之间的映射)是由MMU完成的。操作系统可以利用MMU,把多个虚拟地址映射到同一物理地址,从而在分页技术的支持下,允许应用程序引用大于实际物理内存的虚拟地址。

大部分操作系统使用“页表(Page Table)”来存储虚拟地址与物理地址的映射关系,页面通常是一个简单的数组,pageTable[v] = p,代表虚拟页v与物理页p具有关联关系。为了节省空间,通常会使用多级页表(Multilevel Page Table ),例如Linux在进行32位寻址时,使用二级页表。

分页(Paging)

分页是一种内存管理技术,允许从在主存、辅存之间存取、交换页,共应用程序使用。

当应用程序程序尝试访问的页当前没有映射到物理内存的情况,称为页面错误(Page fault),操作系统采取一种对程序透明的方式来处理页面错误:

  1. 确定页在辅存中的位置
  2. 获取一个空白的页帧(Page Frame)来作为数据的容器
  3. 加载辅存中的页到页帧
  4. 更新页表(Page Table),引用新的页帧
  5. 返回控制器给应用程序,重试导致页面错误的指令

如果处理页面错误时,发现没有足够的内存以获取一个空白页帧,则操作系统会使用一个页面替换算法,将某个现存的页帧从内存中清除,并将其持久化到辅存(如果其内容被修改过)。大部分操作系统使用LRU算法或者基于工作集的算法来进行页面替换。

工作集这一概念,用于确定进程在一定时间区间内需要的内存的量。

在Unix-like的操作系统中,使用术语“交换(Swap)”来描述页面替换这一动作。

x86寄存器
 寄存器 起源 位数 说明 
AX

8086/
8088

16

通用寄存器

尽管属于通用寄存器,但是每个都有附加的特殊用途,例如CX可以作为循环指令的计数器

每个寄存器可以拆分为两个使用,例如AH、AL分别访问AX的高8位、低8位

BX  16 
CX  16 
DX  16 
CS 16  8086起引入,区段寄存器,用于存放绝对地址
CS:代码段寄存器,指向当前执行代码所在内存区域
DS:数据段寄存器,指向当前运行着的程序的数据段,可以将其指向任何具有所属数据的地址
SS:栈段寄存器,指向栈段
ES:额外的段寄存器, 通常跟DI一起用来做指针操作
DS  16 
SS  16 
ES  16 
IP 16 指令指针寄存器,CS与IP共同决定了下一条CPU指令的内存地址,CS:IP相当于程序计数器(PC)
SP 16 栈顶指针寄存器
BP  16  基指针,可以用来指向堆栈或存储器的其它地方,例如用来保存使用局部变量的地址 
SI 16 源/目标索引(指针)寄存器,这两个寄存器通常用来处理数组或字符串。SI通常指向源数组,DI通常指向目的数组,他们通常被用来成块地移动数据,比如移动数组或结构体  
DI  16 
FLAGS   16 标记寄存器,每一位有单独用途,可以指示进位、溢出、结果为零等
EAX 80386             32 通用寄存器,其低16位与原本的AX、BX、CX、DX重叠共用    
EBX  32 
ECX  32 
EDX  32 
EIP 32 指针寄存器,扩展对应16位版本
EBP  32 
ESP  32 
ESI  32 
EDI  32 
FS 32 新增加的两个区段寄存器,没有特定用途

区段寄存器在32位模式下改做为存储器区块的选择子(Selector)寄存器。 

GS  32
EFLAGS 32 标记寄存器,其低16位与原本的FLAGS重叠共用
MM0-
MM7 
MMX       64 MMX寄存器与对应 FPU(浮点运算器)重叠,MMX与浮点运算不可同时使用,必须通过切换选择使用其中一种。
FP0-
FP7 
64 
RAX 64 通用寄存器,其低32位与原本的EAX、EBX、ECX、EDX重叠共用
RBX  64 
RCX  64 
RDX  64 
RIP 64 指针寄存器,扩展对应32位版本
RBP  64 
RSP  64 
RSI  64 
RDI  64 
R8-
R15
64 新增的八个通用寄存器
XMM0-
XMM15
SSE 128

单指令流多数据流(SIMD)寄存器

流式SIMD扩展(Streaming SIMD Extensions)是Intel在AMD的3D Now!发布一年后,在Pentium III中引入的指令集,是对MMX的扩充

SSE最初只加入了XMM0~XMM7这8个寄存器,AMD发布的x86_64加了额外的8个,这8个只能在64位模式下使用

YMM0-
YMM15
AVE 256

单指令流多数据流(SIMD)寄存器

高级矢量扩展(Advanced Vector Extensions)是在2008年提出的x86指令集架构扩展,在2011年Sandy Bridge系列处理器中首次被支持

ZMM0-
ZMM31
AVX-512  512 

单指令流多数据流(SIMD)寄存器 

AVX-512在2013年首次提出,计划在2015年 Knights Landing 处理器中首次支持

ARM架构

ARM,即高级精简指令集机器(Advanced RISC Machine),是一种精简指令集的指令集架构,广泛的使用在嵌入式系统中。ARM具有低成本、高性能、低能耗的特点。到2011年,ARM占有了95%的智能手机、90%的硬盘驱动器、20%的移动电脑处理器份额。

ARM指令设计快速而精简,大多在一个CPU周期内执行,整体电路化,不使用微码。

引导扇区

引导扇区是磁盘、软盘或光盘上的一个区域。其中包含由计算机固件负责加载到内存的机器码。

引导扇区的意义是,允许计算机启动过程能加载相同磁盘上的一个程序(通常是操作系统)。在IBM PC兼容机上,BIOS选择一个启动设备,然后将它的第一扇区拷贝到内存的0x7C00地址。其它系统中,可能完全不一样。

第一扇区可能存放着: MBR、VBR或者任何可执行代码。

MBR(Master Boot Record 主引导记录)是已经被分区的磁盘上的第一个扇区。MBR能够定位到活动分区(Active partition,Bootable)并调用其VBR。

VBR(Volume Boot Record 卷引导记录)可以是未分区磁盘(软盘、U盘)的第一扇区,或者某个分区的第一扇区。VBR可能包含用于加载(当前磁盘/当前分区)操作系统的代码。VBR也可能加载第二阶段引导程序(Bootloader)。

操作系统基本概念
操作系统的外延

一般的,可以把以下内容看作操作系统的组成部分:

  1. 内核
  2. 设备驱动程序
  3. 启动引导程序
  4. 命令行Shell
  5. 其它基本的用户界面工具、文件管理工具、系统管理工具

内核是操作系统的核心所在,通常包括以下部分:

  1. 负责响应中断的中断服务程序
  2. 负责管理多个进程从而分享处理器时间的调度程序
  3. 负责管理进程地址空间的内存管理程序
  4. 负责网络、进程间通信的系统服务程序

内核程序代码独立于普通应用程序,一般处于内核态(亦称系统态)运行。

中断(INTerrupt)

这个概念最初的含义是:外在的事件打断正在执行的程序,转而执行处理这个事件的特定处理程序,处理结束后,回到被打断的程序继续执行。

在实模式下,BIOS提供的中断机制是依赖于以下两部分实现的:

  1. 中断向量表(Interrupt Vector Table):实模式中断机制的重要组成部分,表中记录所有中断号对应的中断服务程序的内存地址
  2. 中断服务程序(Interrupt Services):通过中断向量表的索引对中断进行响应,是一些具有特定功能的程序

在操作系统启动过程中,通常会关闭中断,并把BIOS在内存中的中断向量表、中断服务程序擦除,并替换为操作系统的中断处理机制,然后打开中断。

 中断类型 说明 
时钟中断 该中断在操作系统中频繁发生,例如Linux中可能每10ms就发生一次。时钟中断是进程轮询调度的基础
软中断 用户程序可以通过软中断来进入内核态,执行内核代码
缓冲区

操作系统的“缓冲区”是一个内存区域,主要作为主机与外设(例如硬盘等块设备)进行数据交互的中转站,让主内存区域与外设隔离。

缓冲区包含的数据有:硬盘引导块。

主内存区域存放进程的各种数据,例如程序代码。

系统调用

系统调用是用户程序与操作系统内核交互的接口。通常,用户程序通过C库函数简洁的进行系统调用,库函数与系统调用并不一定是一一对应关系,比如printf函数中包含了write系统调用(将数据写到控制台),同时还包括了数据缓存、格式化等逻辑。

在Linux中,函数system_call是系统调用的总入口,用户程序可以产生“系统调用软中断”,操作系统经由system_call找到具体系统函数,并调用。

系统调用软中断将用户程序与内核隔离——出于安全方面的考虑,用户程序不能直接访问内核——通过触发软中断,用户进程的执行并暂停,并转入内核态执行系统调用函数,然后再返回用户进程暂停处恢复执行,可以说,系统调用是“内核代为执行”的。系统调用函数本质上都是软中断服务程序。

直接调用系统调用是效率低下的操作,因为进入内核态  - 执行内核代码 - 返回用户代码这一过程本身就需要开销。应当尽量减少系统调用的次数,操作系统附带的标准函数库通常可以用来实现这一目的,例如带有I/O缓冲功能的标准I/O库。

用户态与内核态

操作系统的内核代码一般在内核态运行,内核态意味着独立的、受保护的内存空间以及完全的硬件访问权限。内核态与用户态的根本不同在于硬件控制的特权等级。

应用程序的代码则在用户态运行, 它们只能看到允许它们使用的部分系统资源,并且只使用某些特定的系统功能,不能直接访问硬件,也不能访问内核划分给其它程序的内存范围。

但是,应用程序进程在执行过程中,往往需要使用操作系统内核提供的功能,这里就涉及到进程的“权限提升”的问题,亦即从用户态转换到内核态的问题。

80386及以后的CPU包含了若干种特权级别的定义,在段描述符中,包含两位数字用于标记当前所执行代码的特权级,共可表示0、1、2、3四个级别,用户态对应的优先级是3,内核态对应的优先级是0,进程在运行过程中,可能多次改变其特权级别。

降低特权级别的改变有几种方法,其中一种是“中断返回”。当CPU执行指令iret时,硬件会自动把特权级下降为3,即导致进程在用户态运行。Linux系统函数move_to_user_mode函数可以模拟这种中断返回(所谓模拟,是指不发生真正中断的情况下“返回”)。

相应的,用户代码触发(软)中断,则可进入内核态,即提升特权级别。

CPU的活动,在某个时间点上,其活动必然是三者之一:

  1. 运行于用户空间(用户态),执行用户进程
  2. 运行于内核空间(内核态),处于进程上下文, 代表某个特定的进程执行,内核执行系统调用时,就是这一情况
  3. 运行于内核空间(内核态),处于中断上下文, 与任何进程无关,处理某个特定的中断

当CPU空闲的时候,内核可能运行于一个空进程,处于进程上下文,但运行于内核空间。

process-3

进程切换

本段内容不区分进程、线程两个概念。

CPU同一时刻只能运行一条指令,因而它只能同时执行一个进程。在多任务操作系统中,CPU不断的切换其执行的进程,给用户一种多个任务同时在执行的假象。

进程切换可能发生在下列场景:

  1. 时间片用完时:每个进程在创建时,都被赋予有限的时间片,进程在用完时间片后,只要其处于用户态,就会立即切换到其它进程执行
  2. 进程不具备进一步执行(Unrunnable)的条件时:比如进程处于内核态,已经没有代码需要执行,或者下一步执行需要外设提供的数据。这种情况下就可以立即切换到其它进程,以免浪费CPU时间。这种情况典型的例子是等待网络I/O完成

发生进程切换的时候,必然意味着上下文切换。

上下文切换(Context Switch)

除非特别提及,本段内容不区分进程、线程两个概念。

在计算机领域,上下文切换是指存储/恢复进程状态(即上下文)的处理过程,该过程可以使进程恢复到下一次执行的最后状态,从而允许多个进程共享单颗CPU。上下文切换是多任务操作系统的基本特性。

以下三种原因会导致上下文切换:

  1. 多任务(Multitasking):进程不具备进一步执行的条件时,会立即执行上下文切换;对于抢占式多任务系统(Preemptive Multitasking)而言,当进程的时间片( Time Slice)用完时,会触发时钟中断,强制的进行上下文切换
  2. 中断处理:当发生中断时,硬件会自动切换一部分上下文(至少允许中断处理器能返回到被中断的代码处),切换后得到的空间用于存放中断上下文,中断处理器的代码在此上下文中执行,执行完毕后,则恢复到中断前的上下文状态。现代处理器和操作系统倾向于最小化需要切换的上下文部分,以减少中断处理消耗的时间
  3. 内核态与用户态之间切换时:尽管单纯的内核态-用户态切换,并不需要上下文切换,但是某些操作系统还是可能在此时执行上下文切换

上下文包含的内容取决于CPU和操作系统,以Linux 2.6为例,以下内容需要被切换:

  1. CPU寄存器的值,即所谓“硬件上下文”,包含了大量进程实时状态信息
  2. 内核态栈:当进程进入内核态运行时,该栈会被自动创建
  3. 页全局目录(Page Global Directory):与虚拟地址空间有关
单内核与微内核

这是两种不同的操作系统内核设计方式:

  1. 单内核:内核整体上作为一个大的过程来实现,运行在单独的地址空间上。所有内核服务都运行在一个大的内核地址空间上,其间的通信开销是微不足道的
  2. 微内核:操作系统内核仅包含一个很小的函数集,通常包括几个同步原语、一个简单的调度程序、IPC机制,运行在内核之上的若干系统进程实现内存分配、系统调用处理、设备驱动等OS的核心功能。大部分微内核设计者最终都让系统进程运行于内核空间,例如Windows NT内核,这其实违背了微内核设计的原则

单内核设计的优点是:

  1. 设计简单,性能高:所有内核例程运行在单独地址空间上,没有IPC开销。内核例程之间也不会引入上下文切换

微内核设计的优点是:

  1. 模块化:微内核迫使程序员使用模块化方式设计,因为任何操作系统组件都是相对独立的程序,必须通过明确定义的接口与其他组件交互
  2. 易于移植:与硬件相关的代码可以被封装到微内核中
  3. 更加充分的利用内存:暂时不需要的系统进程可以被调出或撤销

Linux是单内核OS,为了达到微内核的优势,内核引入了模块(Module)机制,所谓模块就是一个目标文件,遵循了良好定义的接口,其代码可以在运行时链接到内核(或解除链接)。模块通常包括一组函数,用来实现文件系统、驱动程序等内核上层功能。

POSIX(Portable Operating System Based on Unix)

是IEEE发布的一套标准,该标准定义了一套API,从而使遵循POSIX的操作系统之间可以方便的进行应用程序的移植。所有类UNIX系统都遵循此标准。Windows NT内核也一定程度上实现了POSIX标准。

← 使用Eclipse进行远程调试
Visual Studio知识集锦 →

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Related Posts

  • Apache HTTP Server知识集锦
  • Linux内核学习笔记(一)
  • Linux信号、进程和会话
  • Ubuntu下安装Tomcat7
  • Linux目录层次和配置文件

Recent Posts

  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
  • A Comprehensive Study of Kotlin for Java Developers
  • 背诵营笔记
  • 利用LangChain和语言模型交互
  • 享学营笔记
ABOUT ME

汪震 | Alex Wong

江苏淮安人,现居北京。目前供职于腾讯云,专注容器方向。

GitHub:gmemcc

Git:git.gmem.cc

Email:gmemjunk@gmem.cc@me.com

ABOUT GMEM

绿色记忆是我的个人网站,域名gmem.cc中G是Green的简写,MEM是Memory的简写,CC则是我的小天使彩彩名字的简写。

我在这里记录自己的工作与生活,同时和大家分享一些编程方面的知识。

GMEM HISTORY
v2.00:微风
v1.03:单车旅行
v1.02:夏日版
v1.01:未完成
v0.10:彩虹天堂
v0.01:阳光海岸
MIRROR INFO
Meta
  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org
Recent Posts
  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
    In this blog post, I will walk ...
  • A Comprehensive Study of Kotlin for Java Developers
    Introduction Purpose of the Study Understanding the Mo ...
  • 背诵营笔记
    Day 1 Find Your Greatness 原文 Greatness. It’s just ...
  • 利用LangChain和语言模型交互
    LangChain是什么 从名字上可以看出来,LangChain可以用来构建自然语言处理能力的链条。它是一个库 ...
  • 享学营笔记
    Unit 1 At home Lesson 1 In the ...
  • K8S集群跨云迁移
    要将K8S集群从一个云服务商迁移到另外一个,需要解决以下问题: 各种K8S资源的迁移 工作负载所挂载的数 ...
  • Terraform快速参考
    简介 Terraform用于实现基础设施即代码(infrastructure as code)—— 通过代码( ...
  • 草缸2021
    经过四个多月的努力,我的小小荷兰景到达极致了状态。

  • 编写Kubernetes风格的APIServer
    背景 前段时间接到一个需求做一个工具,工具将在K8S中运行。需求很适合用控制器模式实现,很自然的就基于kube ...
  • 记录一次KeyDB缓慢的定位过程
    环境说明 运行环境 这个问题出现在一套搭建在虚拟机上的Kubernetes 1.18集群上。集群有三个节点: ...
  • eBPF学习笔记
    简介 BPF,即Berkeley Packet Filter,是一个古老的网络封包过滤机制。它允许从用户空间注 ...
  • IPVS模式下ClusterIP泄露宿主机端口的问题
    问题 在一个启用了IPVS模式kube-proxy的K8S集群中,运行着一个Docker Registry服务 ...
  • 念爷爷
      今天是爷爷的头七,十二月七日、阴历十月廿三中午,老人家与世长辞。   九月初,回家看望刚动完手术的爸爸,发

  • 6 杨梅坑

  • liuhuashan
    深圳人才公园的网红景点 —— 流花山

  • 1 2020年10月拈花湾

  • 内核缺陷触发的NodePort服务63秒延迟问题
    现象 我们有一个新创建的TKE 1.3.0集群,使用基于Galaxy + Flannel(VXLAN模式)的容 ...
  • Galaxy学习笔记
    简介 Galaxy是TKEStack的一个网络组件,支持为TKE集群提供Overlay/Underlay容器网 ...
TOPLINKS
  • Zitahli's blue 91 people like this
  • 梦中的婚礼 64 people like this
  • 汪静好 61 people like this
  • 那年我一岁 36 people like this
  • 为了爱 28 people like this
  • 小绿彩 26 people like this
  • 彩虹姐姐的笑脸 24 people like this
  • 杨梅坑 6 people like this
  • 亚龙湾之旅 1 people like this
  • 汪昌博 people like this
  • 2013年11月香山 10 people like this
  • 2013年7月秦皇岛 6 people like this
  • 2013年6月蓟县盘山 5 people like this
  • 2013年2月梅花山 2 people like this
  • 2013年淮阴自贡迎春灯会 3 people like this
  • 2012年镇江金山游 1 people like this
  • 2012年徽杭古道 9 people like this
  • 2011年清明节后扬州行 1 people like this
  • 2008年十一云龙公园 5 people like this
  • 2008年之秋忆 7 people like this
  • 老照片 13 people like this
  • 火一样的六月 16 people like this
  • 发黄的相片 3 people like this
  • Cesium学习笔记 90 people like this
  • IntelliJ IDEA知识集锦 59 people like this
  • Bazel学习笔记 38 people like this
  • 基于Kurento搭建WebRTC服务器 38 people like this
  • PhoneGap学习笔记 32 people like this
  • NaCl学习笔记 32 people like this
  • 使用Oracle Java Mission Control监控JVM运行状态 29 people like this
  • Ceph学习笔记 27 people like this
  • 基于Calico的CNI 27 people like this
Tag Cloud
ActiveMQ AspectJ CDT Ceph Chrome CNI Command Cordova Coroutine CXF Cygwin DNS Docker eBPF Eclipse ExtJS F7 FAQ Groovy Hibernate HTTP IntelliJ IO编程 IPVS JacksonJSON JMS JSON JVM K8S kernel LB libvirt Linux知识 Linux编程 LOG Maven MinGW Mock Monitoring Multimedia MVC MySQL netfs Netty Nginx NIO Node.js NoSQL Oracle PDT PHP Redis RPC Scheduler ServiceMesh SNMP Spring SSL svn Tomcat TSDB Ubuntu WebGL WebRTC WebService WebSocket wxWidgets XDebug XML XPath XRM ZooKeeper 亚龙湾 单元测试 学习笔记 实时处理 并发编程 彩姐 性能剖析 性能调优 文本处理 新特性 架构模式 系统编程 网络编程 视频监控 设计模式 远程调试 配置文件 齐塔莉
Recent Comments
  • qg on Istio中的透明代理问题
  • heao on 基于本地gRPC的Go插件系统
  • 黄豆豆 on Ginkgo学习笔记
  • cloud on OpenStack学习笔记
  • 5dragoncon on Cilium学习笔记
  • Archeb on 重温iptables
  • C/C++编程:WebSocketpp(Linux + Clion + boostAsio) – 源码巴士 on 基于C/C++的WebSocket库
  • jerbin on eBPF学习笔记
  • point on Istio中的透明代理问题
  • G on Istio中的透明代理问题
  • 绿色记忆:Go语言单元测试和仿冒 on Ginkgo学习笔记
  • point on Istio中的透明代理问题
  • 【Maven】maven插件开发实战 – IT汇 on Maven插件开发
  • chenlx on eBPF学习笔记
  • Alex on eBPF学习笔记
  • CFC4N on eBPF学习笔记
  • 李运田 on 念爷爷
  • yongman on 记录一次KeyDB缓慢的定位过程
  • Alex on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • haolipeng on 基于本地gRPC的Go插件系统
  • 吴杰 on 基于C/C++的WebSocket库
©2005-2025 Gmem.cc | Powered by WordPress | 京ICP备18007345号-2