《性能之巅:洞悉系统、企业与云计算》第一章(绪论)和第二章(方法)的笔记,请参考Part 1

本章(操作系统)分为两部分:

  • 背景知识:介绍术语和操作系统基础;
  • 内核:总结Linux和基于Solaris的内核。

术语

与操作系统相关的核心术语:

  • 操作系统:这里指的是安装在系统上的软件和文件,使得系统可以启动和运行程序。操作系统包括内核、管理工具,以及系统库;
  • 内核:内核是管理系统的程序,包括设备(硬件)、内存和CPU调度。它运行在CPU的特权模式,允许直接访问硬件,称为内核态;
  • 进程:一个OS的抽象概念,是用来执行程序的环境。程序通常运行在用户模式,通过系统调用或自陷来进入内核模式(例如,执行设备I/O);
  • 线程:可被调度的运行在CPU上的可执行上下文。内核有多个线程,进程有一个或多个线程;
  • 任务:一个Linux的可运行实体,可以指一个进程(含有单个线程),或一个多线程的进程里的一个线程,或内核线程;
  • 内核空间:内核的内存地址空间;
  • 用户空间:进程的内存地址空间;
  • 用户空间:用户级别的程序和库,如/usr/bin/usr/lib
  • 上下文切换:内核程序切换CPU让其在不同的地址空间上做操作(上下文);
  • 系统调用:一套定义明确的协议,为用户程序请求内核执行特权操作,包括设备I/O;
  • 处理器:处理器是包含有一颗或多颗CPU的芯片;
  • 自陷:信号发送到内核,请求执行一段系统程序(特权操作)。自陷类型包括系统调用、处理器异常,以及中断;
  • 中断:由物理设备发送给内核的信号,通常是请求I/O服务。中断是自陷的一种类型。

更多术语:地址空间、缓冲、CPU、文件描述符、POSIX、寄存器。

背景

内核

内核管理着CPU调度、内存、文件系统、网络协议,以及系统设备(磁盘、网络接口等)。通过系统调用提供访问设备和内核服务的机制。

《性能之巅:洞悉系统、企业与云计算》-操作系统-笔记_系统调用


解读:系统库所画的环有一个缺口,表示应用程序是可以直接进行系统调用的(如果操作系统允许)。

时钟

经典的UNIX内核的一个核心组件是clock()例程,从一个计时器中断执行。每次执行称为一次tick。功能包括更新系统时间、计时器和线程调度时间片的到时结束、维护CPU统计数据、执行callout(内核调度例程)。曾存在过的时钟性能问题:

  • tick延时:对于100Hz的时钟,因为要等待在下一个tick做处理遇到的延时可能会长达10ms。这一问题已经用高精度的实时中断解决,执行可以立即发生而不需要等待;
  • tick开销:现代的处理器有动态电源功能,可在空闲时降低耗能。clock例程会打断这个过程,空闲的系统也会不必要地消耗功率。Linux采用动态tick,这样当系统空闲时,计数器例程(clock)不启动。

现代内核已经把许多功能移出clock例程,放到按需中断中,这是为了努力创造无tick内核。包括Linux在内,clock例程,即系统计时器中断,除了更新系统时钟和更新jiffies计数器之外,执行的工作很少(jiffies是Linux的时间单元,与tick类似)。

内核态

内核是唯一运行在特殊CPU模式的程序,设备的一切访问以及特权指令的执行都是被允许的。由内核来控制设备的访问,用以支持多任务处理,除非明确允许,否则进程之间和用户之间的数据是无法彼此访问的。

《性能之巅:洞悉系统、企业与云计算》-操作系统-笔记_系统调用_02


无论是用户态还是内核态,都有自己的软件执行上下文,包括栈和寄存器。在用户态执行特权指令会引起异常,这会由内核来妥善处理。

上下文切换也会发生在不同进程之间,如CPU调度时。

栈用函数和寄存器的方式记录线程的执行历史。

栈检查是一个对于调试和性能分析非常宝贵的工具。栈可以显示通往当前的执行状态的调用路径,这一点常常可以解释为什么某些方法会被执行。

在执行系统调用时,一个进程的线程有两个栈:一个用户级别的栈和一个内核级别的栈。

《性能之巅:洞悉系统、企业与云计算》-操作系统-笔记_系统调用_03


线程被阻塞时,用户级别的栈在系统调用期间并不会改变,当执行在内核上下文时,线程用的是一个单独的内核级别的栈。(例外,信号处理程序取决于其配置,可以借用用户级别的栈。)

中断和中断线程

中断:内核要响应设备的服务请求,会中断当前的执行。

《性能之巅:洞悉系统、企业与云计算》-操作系统-笔记_性能优化_04


中断服务程序(Interrupt Service Routine)需要通过注册来处理设备中断。这类程序的设计要点是需要运行得尽可能快,以减少对活动线程中断的影响。如果中断要做的工作不少,尤其是还可能被锁阻塞,那么最好用中断线程来处理,由内核来调度。

对于Linux而言,设备驱动分为两半,上半部用于快速处理中断,到下半部的调度工作在之后处理。

中断延时:Interrupt Latency,从中断开始到中断被服务之间的时间。

中断优先级

中断优先级:Interrupt Priority Level,IPL,表示当前活跃的中断服务程序的优先级。

串行I/O的中断优先级很高,这是因为硬件的缓冲通常很小,需要快速服务以避免溢出。

进程

进程是用以执行用户级别程序的环境。包括内存地址空间、文件描述符、线程栈和寄存器。进程里面只有一个程序在执行,用着自己的寄存器和栈。

一个进程中包含有一个或多个线程,操作在进程的地址空间内并且共享着一样的文件描述符(标示打开文件的状态)。线程是一个可执行的上下文,包括栈、寄存器,以及程序计数器。多线程让单一进程可在多个CPU上并发地执行。

进程创建:正常情况下进程是通过系统调用fork()来创建的。fork()用自己的进程号创建自身进程的一个复制,然后调用系统调用exec()才能开始执行不同的程序。

系统调用fork()可用写时拷贝(copy-on-write,COW)的策略来提高性能。这会添加原有地址空间的引用而非把所有内容都复制一遍。一旦任何进程要修改被引用的内存,就会针对修改建立一个独立的副本。这一策略推迟甚至消除对内存拷贝的需要,从而减少内存和CPU的使用。

简化的进程生命周期

《性能之巅:洞悉系统、企业与云计算》-操作系统-笔记_文件系统_05


解读:

  • on-proc:指进程运行在处理器(CPU)上;
  • ready-to-run:指进程可以运行,但还在CPU的运行队列里等待CPU。I/O 阻塞,让进程进入sleep 状态直到I/O 完成进程被唤醒。
  • zombie:状态发生在进程终止,这时进程等待自己的进程状态被父进程读取,或者直至被内核清除。

进程环境示意图:

《性能之巅:洞悉系统、企业与云计算》-操作系统-笔记_缓存_06


解读:

  • 内核上下文信息可用ps(1)命令获取;
  • 文件描述符,指向打开的可在线程间共享的文件;
  • 用户地址空间包括进程的各种内存段:可执行文件、库和堆。

系统调用

系统调用请求内核执行特权的系统例程。可用的系统调用数目是数百个,但需要努力确保这一数目尽可能地小,以保持内核简单。更为复杂的接口应该作为系统库构建在用户空间中,在那里开发和维护更为容易。

系统调用

描述

read()

读取字节

write()

写入字节

open()

打开文件

close()

关闭文件

fork()

创建新进程

exec()

执行新程序

connect()

连接到网络主机

accept()

接受网络连接

stat()

获取文件统计信息

ioctl()

设置IO属性,或者做其他事情

mmap()

把文件映射到内存地址空间

brk()

扩展堆指针

解读:

  • ioctl():用于向内核请求各种各样的操作,特别是针对系统管理工具;
  • mmap():通常用来把可执行文件和库以及内存映射文件映射到进程的地址空间。有时会替代基于brk()malloc()对进程的工作内存做分配,以减少系统调用的频率,提升性能(并不总是这样,内存映射管理会做一些权衡);
  • brk():用于延伸堆的指针,该指针定义进程工作内存的大小。这个操作通常是由系统内存分配库执行的,当调用malloc()内存分配不能满足堆内现有空间时发生。

perf(1)工具执行特权指令来协调性能监测点。并非对每一个行为都添加一个系统调用,而是只添加一个系统调用perf_event_open(),它会用ioctl()返回一个文件描述符。用不同的参数调用ioctl()会执行不同行为。例如,ioctl(fd,PERF_EVENT_IOC_ENABLE)能开启监测点。开发人员可很容易地对参数PERF_EVENT_IOC_ENABLE做添加和修改。

虚拟内存

虚拟内存是主存的抽象,提供进程和内核,它们自己的近乎是无穷的和私有的主存视野。支持多任务处理,允许进程和内核在它们自己的私有地址空间做操作而不用担心任何竞争。它还支持主存的超额使用,如果需要,操作系统可以将虚拟内存在主存和二级存储(磁盘)之间映射。

《性能之巅:洞悉系统、企业与云计算》-操作系统-笔记_性能优化_07


处理器和操作系统的支持使得虚拟内存成为可能,它并不是真实内存。多数操作系统仅仅在需要时将虚拟内存映射到真实内存上,即当内存首次被填充(写入)时。

内存管理

当虚拟内存用二级存储作为主存的扩展时,内核会尽力保持最活跃的数据在主存中。有以下两个内核例程做这件事情:

  • 交换:让整个进程在主存和二级存储之间做移动;
  • 换页:移动称为页的小的内存单元(例如4KB)。

swapping是原始的UNIX方法,会引起严重的性能损耗。paging更高效,经由换页虚拟内存的引入而加到BSD中。两种方法,最近最少使用的内存被移动到二级存储,仅在需要时再次搬回主存。

调度器

UNIX及其衍生的系统都是分时系统,通过划分执行时间,让多个进程同时运行。进程在处理器上和CPU间的调度是由调度器完成的,调度器操作线程,并将它们映射到CPU上。

《性能之巅:洞悉系统、企业与云计算》-操作系统-笔记_文件系统_08


调度器基本的意图是将CPU时间划分给活跃的进程和线程,而且维护一套优先级的机制,这样更重要的工作可以更快地执行。

工作负载分类:

  • CPU密集型:应用程序执行繁重的计算,受到CPU资源的限制;
  • I/O密集型:应用程序执行I/O,计算不多,如Web服务器、文件服务器、交互shell,这些需要的是低延时的响应。当负载增加时,会受到存储I/O或网络资源的限制。

调度器能够识别CPU密集型的进程并降低它们的优先级,可以让I/O密集型工作负载(需要低延时响应)更快地运行。

文件系统

文件接口通常是基于POSIX(Portable Operating System Interface,可移植操作系统接口)标准。内核能够支持多种文件系统类型和实例。

操作系统提供全局的文件命名空间,组织成为一个以根目录/为起点,自上而下的拓扑结构。通过挂载(mounting)可添加文件系统的树,把自己的树挂在一个目录上(挂载点)。这使得遍历文件命名空间对于终端用户是透明的,不用考虑底层的文件系统类型。

《性能之巅:洞悉系统、企业与云计算》-操作系统-笔记_缓存_09


顶层的目录包括:

  • etc:放系统配置文件;
  • usr:系统提供的用户级别的程序和库;
  • dev:设备文件;
  • var:包括系统日志在内的各种文件;
  • tmp:零时文件;
  • home:用户的home目录。

虚线框里的var和home可以是在自身的文件系统实例里,位于不同的存储设备中;能像这个树的其他部分一样,做同样的访问。

某些文件系统类型是由内核动态生成的,诸如/proc/dev

VFS:Virtual File System,虚拟文件系统,是一个对文件系统类型做抽象的内核界面,起源于Sun公司,最初目的是让UNIX文件系统(UFS)和NFS能更容易地共存。

《性能之巅:洞悉系统、企业与云计算》-操作系统-笔记_系统调用_10


VFS接口让内核添加新的文件系统时更加简单,VFS支持全局文件命名空间,用户程序和应用程序能透明地访问各种类型的文件系统。I/O栈:基于存储设备的文件系统,从用户级软件到存储设备的路径被称为I/O栈。示意图如下:

《性能之巅:洞悉系统、企业与云计算》-操作系统-笔记_文件系统_11

缓存

磁盘I/O的延时较长,软件栈中的很多层级通过缓存读取和缓存写入来试图避免这一点。

磁盘I/O缓存层级示例

缓存

实例

应用程序缓存

-

服务器缓存

Apache缓存

缓存服务器

memcached

数据库缓存

MySQL缓冲区高速缓存

目录缓存

DNLC

文件元数据缓存

inode缓存

操作系统缓冲区高速缓存

segvn

文件系统主缓存

ZFS ARC

文件系统次缓存

ZFS L2ARC

设备缓存

ZFS vdev

块缓存

缓冲区高速缓存

磁盘控制器缓存

RAID卡缓存

存储阵列缓存

-

磁盘内置缓存

-

网络

现代内核提供一套内置的TCP/IP网络协议栈,能够让系统用网络进行通信,成为分布式系统环境的一部分。

连接网络的物理设备是网络接口,一般使用网络接口卡(network interface card,NIC)。系统管理员把IP地址关联到网络接口上,这样才能用网络进行通信。网络协议不经常变化,但协议的增强和选项会变化;对于不同的网络接口卡的支持,需要内核有新设备的驱动。

设备驱动

内核必须和各种各样的物理设备通过设备驱动实现通信,设备驱动是用于设备管理和设备I/O的内核软件。设备驱动常常由开发硬件设备的厂商提供。某些内核支持可插拔的设备驱动,这意味着不需要系统重启就可装载或卸载这些设备驱动。

设备驱动提供给设备的接口有字符接口、块接口。字符设备,也称为原始设备,提供无缓冲的设备顺序访问,访问可以是任意I/O尺寸的,也可以小到单一字符,取决于设备本身。这类设备包括键盘和串行口(对于最早的UNIX,还有纸带和行打印机)。

块设备所执行的I/O以块为单位,从前一直是一次512B。基于块的偏移值可随机访问,偏移值在块设备的头部以0开始计数。对于最早的UNIX,块设备接口还为设备的缓冲区提供缓存来提升性能,这相对于主存来说,称为缓冲区高速缓存。

多处理器

支持多处理器使得操作系统可用多个CPU实体来并行地执行工作。通常实现成为对称多处理结构(symmetric multiprocessing,SMP),对所有的CPU都是平等对待的。

CPU交叉调用:多处理器系统,时常会出现CPU需要协调的情况,如内存翻译条目的缓存一致性(通知其他CPU某个缓存条目失效)。CPU可通过CPU交叉调用去请求其他CPU,或所有CPU去立即执行这类工作。交叉调用被设计成能快速执行的处理器中断,以最小化对其他线程中断的影响。

抢占也可使用交叉调用。

抢占

支持内核抢占让高优先级的用户线程可中断内核并执行,这让有严格的响应时间要求的实时系统成为可能。支持抢占的内核称为完全可抢占的,虽然实际上还是会有少量的关键代码路径是不能中断的。

Linux支持自愿内核抢占,在内核代码中的逻辑停止点可以做检查并执行抢占。这就避免完全抢占式内核的某些复杂性,对于常见工作负载提供低延时的抢占。

资源管理

操作系统会提供各种各样可配置的控制,用于精调系统资源,如CPU、内存、磁盘、网络等。Linux开发控制组(control groups,cgroups)并将其整合进2.6.24版本,还为此添加各种控件。

观测性

操作系统由内核、库和程序组成。这些程序包括观测系统活动和性能分析的工具,通常安装在/usr/bin/usr/sbin目录下。用户也可安装第三方工具到系统上以提供额外的观测。

内核

现代内核之间有一些显著区别:支持的文件系统、提供的观测框架、系统调用(syscall)界面、网络栈的架构、对实时的支持,以及CPU、磁盘和网络I/O的调度。

通常更多的系统调用是内核提供给操作系统软件私用的。Linux一直在增加系统调用,Solaris一直在减少系统调用。

UNIX

内核只能是UNIX的代码,不能出于用户的喜好而被替换。基于这个原因,内核应该尽可能少地做真正的决定。这不是意味着做一样的事情,用户可以有成千上万种选择。而是说,做一件事情只允许有一种方法,这种方法是所有可供选择的方法的最小公约数。

Solaris

与性能相关的Sun内核开发如下:

  • NFS:NFS协议让文件可以通过网络共享,并且可以透明地作为全局文件系统树的一部分(挂载)。现在广泛应用的NFS3和NFS4,这两个版本都引入很多性能提升;
  • VFS:虚拟文件系统是一个抽象,这个界面让多种文件系统很容易共存。Sun最初开发它是为了让NFS和UFS可以共存;
  • 页缓存:页缓存用于缓存虚拟内存页,自从它出现以来,就成为了多数操作系统的文件系统缓存的首选(ZFS ARC是一个例外)。页缓存是SunOS 4在重写虚拟内存时引入的,同时也支持共享页;
  • 内存映射文件:能够用于减少文件I/O的开销,是为SVR4重写SunOS的虚拟内存时引入的;
  • RPC:远程过程调用接口;
  • NIS:网络信息服务是一个简单的平面框架,用于在网络里共享信息,包括密码和hosts文件。曾广泛应用多年,现在正让位于LDAP;
  • CacheFS:缓存文件系统,Solaris 2.4(1994)引入,用于在访问缓慢的NFS服务器时提升性能。NFS服务器的性能提升,CacheFS便不再被广泛使用和考虑;
  • 完全抢占内核:一个早期的Sun系统的变种是完全抢占内核,保证了包括实时工作在内的高优先级工作的低延时;
  • 调度器级别:多个调度器级别可以对不同类型工作负载的性能做调整。包括分时(time-sharing,TS)、交互(interactive,IA)、实时(real-time,RT)、系统(system,SYS)、固定(fixed,FX)和FSS(Fair Share Scheduler,公平份额调度器);
  • 多处理器支持:Sun大量地投入于多处理器操作系统的研发,开发出既支持非对称多处理,也支持对称多处理的内核(ASMP和SMP);
  • slab分配器:替代SVR4的buddy分配器,通过让每个CPU缓存预分配的缓冲区能更快地重用,提供更好性能。这一分配器类型以及它的衍生,已成为操作系统的标准;
  • crash分析:Sun开发一套成熟的内核crash dump分析框架,缺省对整个系统开启,还包含modular debugger,可以用于crash dump、内核,以及应用程序的分析;
  • M:N线程调度:为了线程的高效调度目的,在线程和进程之间实现了一个对象,这个对象成为轻量进程(lightweight process,LWP),区别于内核调度,LWP可以有自己的用户级别的调度行为。后来发现Sun的实现存在问题而且不值得那么复杂,在Solaris 9中就被移除,但术语LWP和一些数据结构还是留在Solaris的某些部分里;
  • STREAMS网络栈:Sun在AT&T的STREAMS接口上搭建自己的TCP/IP网络栈,用以提供用户空间与内核空间的通信。而STREAMS网络栈并没有随网络同步发展,在Solaris 10之前,大多数的STREAMS管道都被移除;
  • 64 位支持:Solaris 7内核提供对64位处理器的支持;
  • 锁统计:Solaris 7引入锁性能的统计;
  • MPSS:多种页面尺寸支持让OS可以使用处理器提供的不同尺寸的内存页,包括大页(或者巨型页),以提升内存操作的效率;
  • MPO:Solaris 9加入内存位置优化(Memory Placement Optimization),根据处理器架构(本地性)改进内存分配的方法,可显著地提高内存访问性能;
  • 资源控制:一个用进程或进程组来对各种资源使用做限制的工具,称为projects(之后被Zones使用);
  • FireEngine:针对Solaris 10的一套高性能TCP/IP栈的增强,包括vertical perimeters,对处理包的CPU和内存的本地性做提升,以及IP fanout,在CPU之间做分散负载;
  • Dtrace:一套静态和动态跟踪的框架和工具,可以对整个软件栈做近乎无限的观测,实时并且可以应用于生产环境。随Solaris 10在2005年发布,DTrace是第一次动态跟踪的广泛成功实现,已移植到其他操作系统,包括Mac OS X和FreeBSD,现在是正在移植到Linux的过程中;
  • Zones:一种基于OS的虚拟化技术,允许创建可共享宿主内核的操作系统实例。在Solaris 10发布,这个概念是由FreeBSD的jails在1998年首次完成。相较于其他的虚拟化技术,这两个技术更轻量级且性能更高;
  • Crossbow:一个提供高性能虚拟网络接口和网络带宽资源控制的架构。对于构建可靠的高性能的云至关重要;
  • ZFS:ZFS文件系统提供企业级的特性,随着Solaris 10的update 1一同发布,同时也是开源的。现在可为其他操作系统所用,并成为了许多文件服务器的基础文件系统。

Linux

Linux内核开发总体思路来自于许多前辈:

  • Unix(和Multics):操作系统层级、系统调用、多任务处理、进程、进程属性、虚拟内存、全局文件系统、文件系统权限、设备文件、缓冲区高速缓存;
  • BSD:换页虚拟内存、按需换页、FFS(fast file system,快文件系统)、TCP/IP网络栈、套接字;
  • Solaris:VFS、NFS、页缓存、统一页缓存、slab分配器,以及ZFS和DTrace(在进行中);
  • Plan 9:资源forks(rfork)、为进程间和线程(任务)间的共享设置不同的级别。

与性能相关的Linux内核功能,括号表示内核版本:

  • CPU调度级别:各种先进的CPU调度算法都有开发,包括调度域(2.6.7),对于非一致存储访问架构(NUMA)能做出更好的决策;
  • I/O调度级别:开发不同的块I/O调度算法,包括deadline(2.5.39)、anticipatory(2.5.75)和完全公平队列(CFQ)(2.6.6);
  • TCP拥塞:Linux内核支持更新的TCP拥塞算法,允许按需选择。此外,还有许多对TCP的增强;
  • Overcommit:有out-of-memory(OOM)killer,该策略用较少内存做更多的事情;
  • Futex(2.5.7):fast user-space mutex,用于提供高性能的用户级别的同步原语;
  • 巨型页(2.5.36):由内核和内存管理单元(MMU)支持大型内存的预分配;
  • Oprofile(2.5.43):研究CPU使用和其他活动的系统剖析工具,内核和应用程序都适用;
  • RCU(2.5.43):内核所提供的只读更新同步机制,支持伴随更新的多个读取的并发,提升读取频繁的数据的性能和扩展性;
  • epoll(2.5.46):可以高效地对多个打开的文件描述符做I/O等待的系统调用,提升服务器应用的性能;
  • 模块I/O调度(2.6.10):Linux对调度块设备I/O提供可插拔的调度算法;
  • DebugFS(2.6.11):一个简单的非结构化接口,用该接口内核可以将数据暴露到用户级别,通常为某些性能工具所用;
  • Cpusets(2.6.12):进程独占的CPU分组;
  • 自愿内核抢占(2.6.13):提供低延时调度,并且避免完全抢占的复杂性;
  • inotify(2.6.13):文件系统事件的监控框架;
  • blktrace(2.6.17):跟踪块I/O事件的框架和工具,后迁移到tracepoints中;
  • splice(2.6.17):一个系统调用,将数据在文件描述符和管道之间快速移动,而不用经过用户空间;
  • 延时审计(2.6.18):跟踪每个任务的延时状态;
  • IO审计(2.6.20):测量每个进程的各种存储I/O统计;
  • DynTicks(2.6.21):动态的tick,当不需要时(tickless),内核定时中断不会触发,可节省CPU资源和电力;
  • SLUB(2.6.22):新的slab内存分配器的简化版本;
  • CFS(2.6.23):完全公平调度算法;
  • cgroups(2.6.24):控制组可以测量并限制进程组的资源使用;
  • latencytop(2.6.25):观察操作系统的延时来源的仪器和工具;
  • Tracepoints(2.6.28):静态内核跟踪点(也称静态探针)可以组织内核里的逻辑执行点,用于跟踪工具(之前是内核标记);
  • perf(2.6.31):一套性能观测工具,包括CPU性能计数器剖析、静态和动态跟踪;
  • 透明巨型页(2.6.38):一个简化巨型(大型)内存页面使用的框架;
  • Uprobes(3.5):用户级别软件动态跟踪的基础设施,为其他软件所用(perf、SystemTap等);
  • KVM:基于内核的虚拟机(Kernel-based Virtual Machine,KVM)技术是Qumranet公司为Linux开发的,该公司在2008年被Red Hat公司收购。KVM使得可以创建虚拟的操作系统实例,并运行虚拟机自己的内核。

差异

Linux的优势并非来自内核和操作系统本身,而是来自应用程序包的支持、设备驱动的支持、大型社区,本质上它是开源的。

多数基于Solaris的系统也是开源的(Oracle Solaris除外), 但它们并没有同样广泛的驱动支持。

其他差异,都比较微小。毕竟,Linux和Solaris互相在学习,添加新的功能和特性。

练习

几个问题:

  • 进程、线程和任务之间的区别是什么?
  • 什么是上下文切换?
  • paging和swapping之间的区别是什么?
  • I/O密集型和CPU密集型工作负载之间有什么区别?
  • 描述一下内核的作用?
  • 描述一下系统调用的作用?
  • 描述一下VFS的作用和它在I/O栈里所处的位置?
  • 列出线程离开CPU的原因?
  • 描述一下虚拟内存和按需换页的优点?