System Performance 读书笔记 - 操做系统(1)

2021年11月25日 阅读数:4
这篇文章主要向大家介绍System Performance 读书笔记 - 操做系统(1),主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

本系列是针对 Systems Performance: Enterprise and the Cloud, 2nd Edition (2020) 书籍的读书笔记,加入了一些我的理解以及拓展,而且针对一些难以理解的地方提供了一些额外的参考html

内核(Kernel)

经典模型中,内核在操做系统结构中的位置如图所示:
imagelinux

从里到外分别是:git

  • 硬件(Hardware):操做系统运行在的硬件设备。
  • 内核(Kernel):操做系统的核心软件,内核管理着 CPU 调度、内存、文件系统、网络协议以及各类系统设备(磁盘 IO、网络 IO 等等)。经过系统调用提供服务。
  • 系统调用(System Calls):提供访问硬件设备或者内核服务的程序接口。例如 open, close, read, write, ioctl等,需包含头文件unistd.h
  • 系统库(System Libraries):直接用系统调用可能不太方便,咱们能够使用封装好的库函数进行编程使用。从图上能够看出,这里其实有个缺口,由于应用也能够不使用系统库而是直接使用系统调用。例如像是 Go 语言运行环境,他就使用了本身封装的系统调用层而不是标准库 libc

目前不少操做系统都在这个模型的基础上作了变种,以后咱们会详细分析。github

内核执行

通过不断地迭代,内核目前已经很是庞大,有上百万的代码。内核的执行是按需的,例如当用户级别的应用程序发起了系统调用,或者设备发送了一个中断(interrupt)的时候。另外,某些内核线程回异步执行一些维护性的工做,可能包含内核时钟程序以及内存管理任务,可是这些任务都会尽可能保持轻量级并只占用不多的 CPU 资源。编程

像 Web 服务器这种 I/O 密集型的应用(不断的接受请求返回响应),会常常在内核上下文中执行。计算密集型的应用则会尽可能不打扰内核,能够不中断地在 CPU 上执行。内核调度器会决定那个线程会运行,哪一个会等待,以及调度到哪一个 CPU 上。内核会选择硬件缓存更热或者对于这个进程本地性更好的 CPU,来提升性能。缓存

内核态以及用户态

内核态(kernel mode):运行内核程序的时候,CPU 处于的模式即内核态,在这一状态下,设备的一切访问以及各类特权命令执行都是被容许的。内核控制对于设备的访问来实现多进程处理。除非明确指定,不然进程之间或者用户之间的数据是没法互相访问的服务器

用户态(user mode):运行用户程序的时候,CPU 处于的模式。经过系统调用,会从用户态切换到内核态用更高的权限级别执行:网络

image

用户态切换到内核态是一种模式切换(mode switch),全部的系统调用都会模式切换,某些系统调用还会上下文切换:遇到硬盘 IO 或者网络 IO 的线程会上下文切换到能够运行的线程。这种切换都是有性能损耗的,通常经过以下几种优化来避免:app

  • 用户模式系统调用(User-mode syscalls):能够在用户模式库实现一些系统调用。Linux 经过暴露 virtual dynamic shared object (vDSO)来实现,能够参考:https://man7.org/linux/man-pages/man7/vdso.7.html
  • 内存映射(Memory mappings):用于按需装载内存页(缺页中断),后面还会提到。这样能避免直接访问 IO 形成系统调用。
  • 内核绕开(Kernel bypass):可让用户态程序直接访问设备,例如 DPDK(Data Plane Development Kit),这里推荐一篇关于 DPDK 的文章
  • 内核态应用:例如运行在内核的 TUX 服务器,以及 BPF(Berkeley Packet Filter). 关于 BPF,有一个著名的基于 BPF 实现的工具集合是:https://github.com/iovisor/bcc

link