0%

1 操作系统的基本概念

  1. 操作系统(Operating System,简称 OS)是管理计算机硬件与软件资源的程序,是计算机的基石。
  2. 操作系统本质上是一个运行在计算机上的软件程序 ,用于管理计算机硬件和软件资源。 举例:运行在你电脑上的所有应用程序都通过操作系统来调用系统内存以及磁盘等等硬件。
  3. 操作系统存在屏蔽了硬件层的复杂性。 操作系统就像是硬件使用的负责人,统筹着各种相关事项。
  4. 操作系统的内核(Kernel)是操作系统的核心部分,它负责系统的内存管理,硬件设备的管理,文件系统的管理以及应用程序的管理。 内核是连接应用程序和硬件的桥梁,决定着系统的性能和稳定性。

操作系统的内核(Kernel)

维基百科对于内核的解释: >内核(英语:Kernel,又称核心)在计算机科学中是一个用来管理软件发出的数据 I/O(输入与输出)要求的电脑程序,将这些要求转译为数据处理的指令并交由中央处理器(CPU)及电脑中其他电子组件进行处理,是现代操作系统中最基本的部分。它是为众多应用程序提供对计算机硬件的安全访问的一部分软件,这种访问是有限的,并由内核决定一个程序在什么时候对某部分硬件操作多长时间。 直接对硬件操作是非常复杂的。所以内核通常提供一种硬件抽象的方法,来完成这些操作。有了这个,通过进程间通信机制及系统调用,应用进程可间接控制所需的硬件资源(特别是处理器及 IO 设备)。

早期计算机系统的设计中,还没有操作系统的内核这个概念。随着计算机系统的发展,操作系统内核的概念才渐渐明晰起来了!

简单概括两点:

  • 操作系统的内核(Kernel)是操作系统的核心部分,它负责系统的内存管理,硬件设备的管理,文件系统的管理以及应用程序的管理。
  • 操作系统的内核是连接应用程序和硬件的桥梁,决定着操作系统的性能和稳定性。

中央处理器(CPU,Central Processing Unit)

关于 CPU 简单概括三点:

  • CPU 是一台计算机的运算核心(Core)+控制核心( Control Unit),可以称得上是计算机的大脑
  • ** CPU 主要包括两个部分:控制器+运算器。**
  • CPU 的根本任务就是执行指令,对计算机来说最终都是一串由“0”和“1”组成的序列。

CPU vs Kernel(内核)

可以简单从下面两点来区别:

  • 操作系统的内核(Kernel)属于操作系统层面,而 CPU 属于硬件。
  • CPU 主要提供运算,处理各种指令的能力。内核(Kernel)主要负责系统管理比如内存管理,它屏蔽了对硬件的操作。

2 操作系统的基本特性

操作系统的基本特性是并发性、共享性、虚拟性、异步性。

并发性

并行性和并发性(Concurrence)是既相似又有区别的两个概念,并行性是指两个或多个事件在同一时刻发生;而并发性是指两个或多个事件在同一时间间隔内发生。在多道程序环境下,并发性是指在一段时间内宏观上有多个程序在同时运行,但在单处理机系统中,每一时刻却仅能有一道程序执行,故微观上这些程序只能是分时地交替执行。(宏观并发微观串行)

并行需要硬件支持,如多流水线、多核处理器或者分布式计算系统

操作系统通过引入进程和线程,使得程序能够并发运行。

共享性

指系统中的资源可供内存中多个并发执行的进程(线程)共同使用,相应地,把这种资源共同使用称为资源共享,或称为资源复用。目前主要实现资源共享的方式有:

  • 互斥共享方式
  • 同时访问方式
互斥共享方式

当一个进程 A 要访问某资源时,必须先提出请求。如果此时该资源空闲,系统便可将之分配给请求进程 A 使用。此后若再有其它进程也要访问该资源时(只要 A 未用完),则必须等待。仅当 A 进程访问完并释放该资源后,才允许另一进程对该资源进行访问。我们把这种资源共享方式称为互斥式共享,而把在一段时间内只允许一个进程访问的资源称为临界资源或独占资源,例如打印机。

同时访问方式

系统中还有另一类资源,允许在一段时间内由多个进程“同时”对它们进行访问。这里所谓的“同时”,在单处理机环境下往往是宏观上的,而在微观上,这些进程可能是交替地对该资源进行访问。典型的可供多个进程“同时”访问的资源是磁盘设备,一些用重入码编写的文件也可以被“同时”共享,即若干个用户同时访问该文件。

虚拟性

虚拟技术把一个物理实体转换为多个逻辑实体。

主要有两种虚拟技术:时(时间)分复用技术和空(空间)分复用技术。

多个进程能在同一个处理器上并发执行使用了时分复用技术,让每个进程轮流占用处理器,每次只执行一小个时间片并快速切换。

虚拟内存使用了空分复用技术,它将物理内存抽象为地址空间,每个进程都有各自的地址空间。地址空间的页被映射到物理内存,地址空间的页并不需要全部在物理内存中,当使用到一个没有在物理内存的页时,执行页面置换算法,将该页置换到内存中。

异步性

在多道程序环境下允许多个进程并发执行,但只有进程在获得所需的资源后方能执行。在单处理机环境下,由于系统中只有一台处理机,因而每次只允许一个进程执行,其余进程只能等待。进程是以人们不可预知的速度向前推进,此即进程的异步性。

3 操作系统的基本功能

操作系统的基本功能包括进程管理、内存管理、文件管理、设备管理。

  • 进程管理:进程控制、进程同步、进程通信、死锁处理、处理机调度等
  • 内存管理:内存分配、地址映射、内存保护与共享、虚拟内存等
  • 文件管理:文件存储空间的管理、目录管理、文件读写管理和保护等
  • 设备管理:完成用户I/O请求,方便用户使用各种设备,并提高设备的利用率,主要包括缓冲管理、设备管理、设备处理、虚拟设备等。

4 什么是系统调用/用户态和系统态是?

根据进程访问资源的特点,可以把进程在系统上的运行分为两个级别:

  • ** 用户态(user mode) **: 用户态运行的进程或程序可以直接读取用户程序的数据。
  • 系统态(kernel mode):可以简单的理解系统态运行的进程或程序几乎可以访问计算机的任何资源,不受限制。

我们运行的程序基本都是运行在用户态,如果要调用操作系统提供的系统态级别的子功能,那就需要系统调用了!

也就是说在运行的用户程序中,凡是与系统态级别的资源有关的操作(如文件管理、进程控制、内存管理等),都必须通过系统调用方式向操作系统提出服务请求,并由操作系统代为完成。

这些系统调用按功能大致可分为如下几类:

  • 设备管理。完成设备的请求或释放,以及设备启动等功能。
  • 文件管理。完成文件的读、写、创建及删除等功能。
  • 进程控制。完成进程的创建、撤销、阻塞及唤醒等功能。
  • 进程通信。完成进程之间的消息传递或信号传递等功能。
  • 内存管理。完成内存的分配、回收以及获取作业占用内存区大小及地址等功能。

为什么要有用户态与内核态?

在 cpu 的所有指令中,有些指令是非常危险的,如果使用不当,将会造成系统崩溃等后果。为了避免这种情况发生,cpu 将指令划分为特权级(内核态)指令和非特权级(用户态)指令。

对于那些危险的指令只允许内核及其相关模块调用,对于那些不会造成危险的指令,就允许用户应用程序调用。

  • 内核态(核心态,特权态): 内核态是操作系统内核运行的模式。 内核态控制计算机的硬件资源,如硬件设备,文件系统等等,并为上层应用程序提供执行环境。
  • 用户态: 用户态是用户应用程序运行的状态。 应用程序必须依托于内核态运行,因此用户态的操作权限比内核态是要低的,如磁盘,文件等,访问操作都是受限的。
  • 系统调用: 系统调用是操作系统为应用程序提供能够访问到内核态的资源的接口。

用户态切换到内核态的几种方式

  • 系统调用: 系统调用是用户态主动要求切换到内核态的一种方式,用户应用程序通过操作系统调用内核为上层应用程序开放的接口来执行程序。
  • 异常: 当 cpu 在执行用户态的应用程序时,发生了某些不可知的异常。于是当前用户态的应用进程切换到处理此异常的内核的程序中去。
  • 硬件设备的中断: 当硬件设备完成用户请求后,会向 cpu 发出相应的中断信号,这时 cpu 会暂停执行下一条即将要执行的指令,转而去执行与中断信号对应的应用程序,如果先前执行的指令是用户态下程序的指令,那么这个转换过程也是用户态到内核台的转换。

5 计算机的局部性原理

一个编写良好的计算机程序常常具有良好的局部性,即他们更加倾向于引用邻近于其他最近引用过的数据项的数据项,或者最近引用或的数据项本身,这种特性,常常称为局部性原理。局部性由两种不同的形式:时间局部性和空间局部性

  • 时间局部性:被引用过一次的内存位置很有可能在不久的将来再次被多次引用。
  • 空间局部性:一个内存被引用过了,那么极有可能在不久的将来会引用器附近的内存位置。在高速缓存中的表现形式是以数据块的形式进行缓存,弥补未命中时的惩罚

我们应该理解局部性原理,因为一般而言,一个良好局部性的程序比局部性差的程序运行得更快,这是由现代计算机系统得设计结构所决定得,在现代计算系统得各个层次之哦你给,都引入了局部性原理:

  • 在硬件层,计算机设计者通过引入称为高速缓存存储器这样小而快得快速存储器来保存最近引用得指令和数据项,从而提高对主存得访问速度。
  • 在操作系统中,系统使用主存作为虚拟地址空间,来存储最近被引用得数据项,来避免因从磁盘取数据过慢而导致CPU资源的浪费
  • 类似的,用主存来缓存磁盘文件中最近被使用的磁盘块。
  • 局部性原理在应用程序中也有应用,入Web浏览器将最近引用的文档放在本地磁盘上,利用的就是时间局部性。
阅读全文 »

1 链接器

1.1 链接是什么

链接是将各种代码和数据片段收集并组合成为一个单一文件的过程,这个文件可被加载到内存并执行。

  • 链接可以执行与编译时,也就是源代码被翻译成机器代码时;
  • 也可以执行与加载时,也就是在程序被加载器(loader)加载带内存并执行时
  • 甚至也可执行于运行时,也就是有程序来执行

链接器在开发中是一个关键角色,因为它使得分离编译成为可能,我们不用将一个大型的应用程序组织为一个巨大的源文件,而是可以分解成更小、更好管理的模块。可以单独修改和编译这些模块。理解链接有以下的好处:

  • 理解链接器将帮助你构造大型程序。构造大型程序的程序员经常会遇到缺少模块、库或者不兼容版本引起的链接器错误,当你理解了链接器如何解析引用、什么是库以及链接器是如何使用库来解析引用时,你就能够较好的解决这类问题

  • 理解链接器将帮助你避免一些危险的编程错误。Linux链接器解析引用时所做的决定可以不动声色影响你程序的正确性。在默认情况下,错误的定义多个全局变量的程序将通过链接器,而不产生任何警告信息。

  • 理解链接器将帮助你理解语言的作用域规则是如何实现的。全局变量和局部变量、static变量和static函数,在低层到底有何区别?

  • 理解链接器帮助你理解其他重要系统概念。链接器产生的可执行目标文件咋子系统功能中扮演关键角色,如加载运行程序、虚拟内存、分页、内存映射。

  • 理解链接器将使你能够利用共享库。共享库和动态链接在现代操作系统日益重要,掌握如何动态链接原理极其重要。

阅读全文 »

1 存储技术

作为一名程序员,你必须了解存储器的层次结构,因为它对应用程序的性能有着巨大的影响。

  • 如果你的数据是在cpu寄存器上,那么指令执行期间在0个周期就能访问到
  • 如果是在高速缓存中,需要4-75个周期
  • 如果在主存,需要上百个周期
  • 如果是在磁盘,那么就需要大约几千万个周期,时间大概是毫秒级,比主存慢10万倍,比高速缓存慢100万倍

1.1 随机访问存储器

随机访问存储器(RAM)有两类:静态和动态。静态RAM(SRAM)比动态DRAM(DRAM)更快,但也更贵,因此SRAM一般集成在CPU上作为高速缓存,DRAM则作为主存。断电以后,DRAM和SRAM都会丢失它们的信息

访问主存:每次CPU和主存之间的数据传送都是通过一系列的步骤来完成,这些步骤称为总线事务读事务从主存传输数据到CPU,写事务从CPU传送数据到主存。总线是一组并行的导线,能携带地址、数据和控制信号。

阅读全文 »

1 导读

程序优化涉及的范围实在是太广了,几乎每个层面都可以进行优化,比如撰写<编译器友好型>以及<缓存友好型>的程序,针对不同的目标硬件平台还可能进行特定的优化,等等,优化的难点在于你需要对系统有充分理解,当然了在你做优化之前首先要保证原始程序功能正确(并且有回归测试),否则一切都是徒劳。

首先需要理解,哪些因素会影响程序的性能

阅读全文 »

内存对齐规则

在C/C++中的结构体或类,存在内存对齐问题。内存对齐是为了方便计算机进行寻址,优化寻址速度的一个措施,其代价是消耗不必要的内存空间。

内存对齐遵循以下规则:

  • 第一个成员在与结构体变量偏移量为0的地址处。
  • 其他成员变量都放在对齐数(成员的大小和默认对齐数的较小值)的整数倍的偏移地址处。
    • 对齐数=编译器默认的一个对齐数与该成员大小的较小值。(不同的编译器其默认对齐数不同,64位系统中VS默认的对齐数是8,在Linux中没有默认的对齐数)
    • 可以在程序开端声明#pragma pack(数字)来设置默认对齐值
  • 结构体总大小为最大对齐数(每个成员变量都有一个对齐数 )的整数倍。
  • 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。--->最大对齐数肯定不超过默认对齐数

示例:VS运行(默认对齐数为8)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
typedef struct test2
{
int a;//4-->8,占0,1,2,3地址处,后续补4,5,6,7
double c;//8,但由于其只能放在与首地址偏移量为8的地址上,因此4,5,6,7作为填补空缺,它从8存储
};

typedef struct testMemory
{
int a;//4-->8
long b;//8
char c;//1
struct test2 l;//16
};

cout <<sizeof(test2) << " " << sizeof(testMemory) << endl;

输出:
1
16 40

class类

在C++中,class与struct是相同的,除了:

  • 两者中如果不对成员不指定公私有,struct默认是公有的,class则默认是私有的

  • class默认是private继承, 而struct默认是public继承

因此,对于struct的对齐规则同样是class的对齐规则,在c++中,还必须注意在存在虚函数时类有一个虚表指针的情况:(在64位中指针大小为8字节,32为4字节)

1
2
3
4
5
6
7
8
9
 class my {
private:
int a;
double b;
char c;
virtual int m() { return 0; }
virtual int s(){return 0;}
};
//sizeof(my)为32:8+8+8+8

程序的机器级表示

在本章,会学习观察汇编代码和机器代码。说到汇编语言就不得不提编译器和汇编器。**编译器是基于编程语言规则、目标机器的指令集和操作系统遵循的惯例,经过一系列阶段如图:

gcc编译器以汇编代码的形式产生输出,然后gcc调用汇编器和链接器生成二进制机器文件和可执行文件。对于Linux机,可以使用 gcc -Og -S xxx.c来进行学习。因为参数-Og表明不进行优化,这可以让汇编代码尽可能地保持和C源码一样的顺序,位置,排列等。

阅读全文 »

Here's something encrypted, password is required to continue reading.
阅读全文 »