进程与线程

主要掌握进程与线程的区别和联系

进程是系统资源分配的最小单位,线程是程序执行的最小单位;
进程使用独立的数据空间,线程共享进程的数据空间;

线程调度

简单了解几种线程调度算法以及这两个衡量批处理系统的调度性能

  • 周转时间:作业结束完成时间-作业进入系统时间
  • 带权周转时间:周转时间/所需运行时间

先来先服务调度

  • 策略:在到达系统的一批作业中,先来先服务算法(FCFS)按照作业进入系统的先后次序挑选作业,先进入系统优先被挑选,这是一种非剥夺式算法;
  • 效果:有利于CPU繁忙型作业,不利于I/O繁忙型作业;

优先级调度

  • 策略:优先级调度算法根据确定的优先级选取进程/线程,每次总是选择就绪队列中优先级最高者运行;优先级调度算法可以采用剥夺或者非剥夺方式,如果就绪队列中出现优先级更高的进程/线程,剥夺式调度可立刻执行该进程/线程,非剥夺式等待当前运行进程结束或者出现等待时间主动让出处理器后,才会调度另一进程投入运行。
  • 优先级规定者有是用户或系统;
  • 优先级还可分为静态优先级和动态优先级;

多级反馈队列调度

  • 多级反馈队列调度算法建立两个或多个就绪进程队列,每个队列赋予不同的优先级,较高优先级一般分配给较短的时间片。处理器每次从高优先级就绪队列中选取可占用处理器的进程,只有在无进程时,才会从较低优先级就绪队列中选取进程,同一队列中的进程按照先来先服务原则排队。开始工作时,新锦成首先进入高优先级队列等候调度,若能在该优先级的一个时间片内执行完成则进程撤离系统,否则进入低一级队列等候调度,若处理器正在执行低优先级队列进程时,若新的进程到达高优先级就绪队列,则处理器暂停当前低优先级队列进程的执行,转而执行高优先级队列中新到进程,因此,多级反馈队列调度是一种剥夺式调度。
  • 不足:多级反馈队列调度存在饥饿问题,当新的进程不断到来时,低优先级队列中的进程将长时间得不到调度

时间片轮转调度

  • 调度程序每次将CPU分配给就绪队列中的首进程使用一个时间片,就绪队列中的每个进程轮流运行一个时间片,当这个时间片耗尽时,强迫当前线程让出处理器,排到就绪队列尾部,等候下一轮调度。是一种剥夺式调度,系统消耗在进程切换上的开销比较大,那么时间片大小的选取就显得非常重要。

高响应比优先调度

  • 响应比=1+已等待时间/作业处理时间
  • 策略:每当调度一个作业的时,都要计算后背作业队中每个作业的响应比,选择响应比最高者投入运行。对于FCFS,只考虑用户等待时间,对于SJF,只考虑计算时间,而高响应比优先调度(HRRF)采用的响应比既考虑了等待时间又考虑了作业处理时间,所以是二者折中的调度算法,是一种非剥夺式调度。

进程/线程切换的步骤

进程上下文

进程上下文包含了进程执行所需的所有信息

  • 用户地址空间:包括程序代码,数据,用户堆栈等;
  • 控制信息:进程描述符,内核栈等;
  • 硬件上下文:(注意中断也要保存硬件上下文只是保存的方法不同)。

进程切换的步骤

  • .切换页目录以使用新的地址空间
  • 切换内核栈
  • 切换硬件上下文

线程切换与进程切换的对比

  • 对于linux来说,线程和进程的最大区别就在于地址空间。对于线程切换,第1步是不需要做的,第2和3步是进程和线程切换都要做的。所以明显是进程切换代价大

线程切换与进程切换的代价对比

  • 线程上下文切换和进程上下文切换一个最主要的区别是线程的切换虚拟内存空间依然是相同的,但是进程切换是不同的。这两种上下文切换的处理都是通过操作系统内核来完成的。内核的这种切换过程伴随的最显著的性能损耗是将寄存器中的内容切换出。
  • 外一个隐藏的损耗是上下文的切换会扰乱处理器的缓存机制。简单的说,一旦去切换上下文,处理器中所有已经缓存的内存地址一瞬间都作废了。还有一个显著的区别是当你改变虚拟内存空间的时候,处理的页表缓冲(processor’s Translation Lookaside Buffer (TLB))或者相当的神马东西会被全部刷新,这将导致内存的访问在一段时间内相当的低效。但是在线程的切换中,不会出现这个问题。

进程间通信 IPC

共享存储

在内存中创建一个共享空间,两个进程对共享空间的访问必须是互斥的(互斥访问通过操作系统提供的工具实现),操作系统只提供共享空间和同步操作工具(P V操作)。

共享存储分为两种

  • 一种是基于数据结构的共享:比如共享空间只能存放一个长度为10 的数组,这种共享方式速度慢、限制多,是一种低级通信方式。
  • 另一种是基于存储区的共享:在内存中划出一块共享存储区,数据的形式、存放位置都由进程控制,而不是操作系统,是一种高级通信方式。

管道通信

  • 管道:管道是指用于连接读写进程的一个共享文件,又名pipe文件。其实就是在内存中开辟一个大小固定的缓冲区。管道之恩那个采用半双工通信,如果要实现双向同时通信,则需要设置两个管道。
  • 各进程要互斥的访问管道
  • 数据以字符流的形式写入管道,当管道写满时,写进程的write()系统调用将被阻塞,等待读进程将数据取走。当读进程将数据全部取走后,管道变空,此时进程的read()系统调用将会被阻塞。
  • 如果没写满,就不允许读,如果没读空,就不允许写。
  • 数据一旦被读出,就从管道中被抛弃,这就意味着读进程最多只能有一个,否则会有都错数据的情况。

消息传递

  • 进程间数据交换以格式化的信息为单位。进程通过操作系统提供的“发送消息/接收消息”两个原语进行数据交换
  • 格式化的消息分为消息头和消息体:消息头包括:发送进程ID、接受进程ID、消息类型、消息长度等格式化的信息(计算机网络中发送的报文其实就是一种格式化的消息)

消息传递有两种方式

  • 直接通信方式:将消息直接挂到接受进程消息缓冲队列上。
  • 简介通信方式:将消息发送到中间实体(信箱)中,因此也称为信箱通信方式。

协程

简单了解协程更轻量化,是在用户态进行调度,切换的代价比线程上下文切换低很多
了解:极高的执行效率:因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显;不需要多线程的锁机制:因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。
了解一些Java的第三方协程框架,比如Kilim 、Fiber .

Linux常用命令

重点掌握awk top netstat grep less tail

内存分页管理与Swap机制(了解)

内存分页

分页存储管理将全部内存分成长度相等的若干份,每一块称为一个物理块或页框,作业也自动被系统分为于每个物理块相等的若干份,每一份称为一页或者一个页面。

Swap机制

当Linux内存不足时就会触发swap(交换)机制, swap机制是什么东西呢?
swap机制其实就是将外存(如硬盘)当内存使用, 怎么可以把外存当内存使用呢? 原理就是当系统内存不够用的时候, 内核会选择某些进程, 把其使用较少的内存的内容交换(swap)到外存中,然后把内存让给需要的进程使用.
那么Linux内核会把哪些内存交换到外存去呢? 在新版的Linux内核会使用LRU算法计算出那些使用比较少的内存交换到外存中.

任务队列与CPU Load(了解)

CPU利用率:显示的是程序在运行期间实时占用的CPU百分比
CPU负载:显示的是一段时间内正在使用和等待使用CPU的平均任务数。CPU利用率高,并不意味着负载就一定大。

操作系统面试要点_操作系统
上图1个电话亭可以理解为一个CPU核心。从上图的过程中可以看到load的概念,而使用率始终100%。

扩展知识点(了解)

内存屏障

内存屏障,也称 内存栅栏, 内存栅障, 屏障指令等, 是一类 同步屏障指令,使得CPU或编译器在对内存随机访问的操作中的一个同步点,使得此点之前的所有读写操作都执行后才可以开始执行此点之后的操作

指令乱序

只要是熟悉计算机底层系统的同学就会知道,程序里面的每行代码的执行顺序,有可能会被编译器和cpu根据某种策略,给打乱掉,目的是为了性能的提升,让指令的执行能够尽可能的并行起来。知道指令的乱序策略很重要,原因是这样我们就能够通过barrier等指令,在正确的位置告诉cpu或者是编译器,这里我可以接受乱序,那里我不能接受乱序等等。从而,能够在保证代码正确性的前提下,最大限度地发挥机器的性能。
乱序执行就是说把原来 有序执行的 指令列表,在保证执行结果一致的情况下 根据 指令依赖关系及指令执行周期 重新安排执行顺序。例如以下指令(a = 1;b=a;c=2;d=c)在CPU中就很可能被重排序成为以下的执行顺序(a=1;c=2;b=a;d=c;),这样的话,4条指令都可以高效的在流水线中运转了。

分支预测

从P5时代开始的一种先进的数据处理方法,由CPU来判断程序分支的进行方向,能够更快运算速度。

CPU亲和性(affinty)

分为软亲和性和硬亲和性

软亲和性

就是进程要在指定的 CPU 上尽量长时间地运行而不被迁移到其他处理器,Linux 内核进程调度器天生就具有被称为 软 CPU 亲和性(affinity) 的特性,这意味着进程通常不会在处理器之间频繁迁移。这种状态正是我们希望的,因为进程迁移的频率小就意味着产生的负载小。

硬亲和性

简单来说就是利用linux内核提供给用户的API,强行将进程或者线程绑定到某一个指定的cpu核运行。

Netfilter与iptables

这里有一篇文章