前言
在看狂神频道的时候偶然发现下图,感触颇深。特别在当今【程序 = 业务 + 框架】思想盛行的开发者中,夯实基础基础显得格外重要,因此开此专栏总结记录。
操作系统
首先来看看操作系统相关知识的汇总,操作系统支持对于服务问题的排查定位十分重要。其中这张脑图左上角的进程与线程部分是一个非常重要的考察点:
进程与线程
-
区别联系:首先需要掌握他们的区别和联系。
-
进程:指在系统中正在运行的一个应用程序;程序一旦运行就是进程;进程——资源分配的最小单位。
线程:系统分配处理器时间资源的基本单元,或者说进程之内独立执行的一个单元执行流。线程——程序执行的最小单位。
-
进程是系统资源分配的最小单位,线程是程序执行的最小单位。
- 一个进行中的程序就是一个进程,在程序中不同的操作就是不同的线程;
-
进程使用独立的数据空间,而线程共享进程的数据空间。
- 一个运行中的程序(进程)使用其独立的数据空间,而线程在进程中调用程序的数据空间。
-
-
线程调度:简单了解线程的几种调度算法就可以了。
-
-
图表介绍,十分简单明了
操作系统内核对线程的调度非常有意思,因为他的一系列思想和方法论都能从生活和业务开发中找到影子,比如:
- 超市收银台会分多个收银通道,快速通道针对那些提篮子的客户,慢速通道针对那些推购物车的客户,从而减少提篮子客户的付款等待时间,设想一下,若某个客户只买了几件物品,但是不巧正好排到了购买了一车物品的客户后面,他的购物体验就会差一些。
- 银行营业厅的叫号系统,他会按照VIP客户、普通客户分出多个号段的排队序号,VIP客户的响应速度会快一些,普通客户的响应速度会慢一些。
- 在内容处理系统中,在处理能力一定的情况下,我们也会按照文章来源的不同进行调度处理,优先快速响应高优先级文章的处理。
- 在融合存储系统中,会对不同业务的主机I/O请求设置不同的优先级,优先保证重要业务的I/O性能(并发和延迟)。
引用的文章介绍得十分详细,在此只做简单的摘要:
-
-
先进先出算法(FIFO,First-In-First-Out)
按照任务进入队列的顺序,依次调用,执行完一个任务再执行下一个任务,只有当任务结束后才会发生切换。
优点:
- 最少的任务切换开销(因为没有在任务执行过程中发生切换,故任务切换开销为0)
- 最大的吞吐量(因没有任务切换开销,在其他一定的情况下,吞吐量肯定是最大的)
- 最朴实的公平性(先来先做)
缺点:
- 平均响应时间高:耗时只需10毫秒的任务若恰巧在耗时1000毫秒的任务后到来,他则需要1010毫秒才能执行完成,绝大部分时间都花在等待被调度了。
适用场景: 队列中任务的耗时差不多的场景。
-
时间片轮转算法(Round Robin)
给队列中的每个任务一个时间片,第一个任务先执行,时间片到了之后,将此任务放到队列尾部,切换到下个任务执行,这样能解决SJF中耗时长任务饥饿的问题。算法介于FIFO和SJF之间,若时间片足够大,则退化到FIFO,若分片足够小(假设不考虑任务切换的开销),则任务的完成时间顺序是以耗时从小到大排列(相比SFJ,任务执行的绝对时间会长,取决于队列中任务的个数)。
优点:
- 每个任务都能够得到公平的调度
- 耗时短的任务即使落在耗时长的任务后面,也能够较快的得到调度执行
缺点:
- 任务切换引起的调度开销较大,需要多次切换任务上下文(特别是CPU的Cache,多次切换容易导致Cache完全不命中,需要重新从内存加载,这个非常耗时)
- 时间片不太好设置 (若设置短了,调度开销大,若设置长了,极端情况是退化到FIFO)
**适用场景:**队列中耗时差不多的任务(比如,多路视频流处理)
**不适用场景:**计算型任务和I/O型任务混合的队列
-
先来先服务调度
-
优先级调度
-
多级反馈队列调度
-
高响应比优先调度算法
-
小结:
- FCFS(先来先服务),SJF(短作业优先调度算法),HRRN(高响应比优先调度算法)三种算法主要关心对用户的公平性、平均周转时间、平均等待时间等评价系统整体性能的指标,并不关心相应时间,也不区分任务的紧急程度,交互性糟糕。因此,这三种方式适用于早期的批处理系统。
- 时间片轮转调度算法(RR),优先级调度算法,多级反馈队列调度算法注重响应时间,公平性等,因此,这三种算法适用于交互式系统。
-
-
线程切换步骤:线程切换的步骤主要是了解线程的上下文切换,
-
明白线程切换的代价
http://www.jb51.net/article/102004.htm
进程切换分两步:
1.切换页目录以使用新的地址空间
2.切换内核栈和硬件上下文
对于linux来说,线程和进程的最大区别就在于地址空间,对于线程切换,第1步是不需要做的,第2是进程和线程切换都要做的。
切换的性能消耗:
1、线程上下文切换和进程上下问切换一个最主要的区别是线程的切换虚拟内存空间依然是相同的,但是进程切换是不同的。这两种上下文切换的处理都是通过操作系统内核来完成的。内核的这种切换过程伴随的最显著的性能损耗是将寄存器中的内容切换出。
2、另外一个隐藏的损耗是上下文的切换会扰乱处理器的缓存机制。简单的说,一旦去切换上下文,处理器中所有已经缓存的内存地址一瞬间都作废了。还有一个显著的区别是当你改变虚拟内存空间的时候,处理的页表缓冲(processor’s Translation Lookaside Buffer (TLB))或者相当的神马东西会被全部刷新,这将导致内存的访问在一段时间内相当的低效。但是在线程的切换中,不会出现这个问题。
-
-
Linux下的IPC(进程之间的通信)
- 在进程与线程部分还有一个比较常见的考察点,就是进程间通信,也就是ipc。这部分在面试中间件研发的相关职位时,经常会考察,需要了解这6种进程通信方式的原理和适用场景:
- pipe
- MessageQueue
- 共享内存
- UnixSocket
- Singal
- Semaphore
- 例如竞争间数据共享的场景。可以使用共享内存进程间数据交换的场景。可以使用unix socket 或者消息队列。
- 在进程与线程部分还有一个比较常见的考察点,就是进程间通信,也就是ipc。这部分在面试中间件研发的相关职位时,经常会考察,需要了解这6种进程通信方式的原理和适用场景:
-
协程:
-
最后协程部分简单了解协程更轻量化是在用户态进行调度切换的代价:
-
学习博客:
小灰出品,必属精品
协程(Coroutine,又称微线程)是一种比线程更加轻量级的存在,协程不是被操作系统内核所管理,而完全是由程序所控制。协程与线程以及进程的关系见下图所示。
协程可以比作子程序,但执行过程中,子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。协程之间的切换不需要涉及任何系统调用或任何阻塞调用
协程只在一个线程中执行,是子程序之间的切换,发生在用户态上。而且,线程的阻塞状态是由操作系统内核来完成,发生在内核态上,因此协程相比线程节省线程创建和切换的开销
协程中不存在同时写变量冲突,因此,也就不需要用来守卫关键区块的同步性原语,比如互斥锁、信号量等,并且不需要来自操作系统的支持。
协程适用于IO阻塞且需要大量并发的场景,当发生IO阻塞,由协程的调度器进行调度,通过将数据流yield掉,并且记录当前栈上的数据,阻塞完后立刻再通过线程恢复栈,并把阻塞的结果放到这个线程上去运行。
-
Linux系统常用命令:
大部分互联网公司的服务都是运行在linux 系统上的,因此linux 命令也是面试时的常考点。
这部分其实主要考察的是。候选人是否有线上问题排查的经验,重点学习(以下命令都可以通过在linux系统中加上 --help 进行学习):
-
awk
- awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入(stdin)、一个或多个文件,或其它命令的输出。(比较高级的指令,相对少用)
-
top
-
top命令 可以实时动态地查看系统的整体运行情况,是一个综合了多方信息监测系统性能和运行信息的实用工具。
-
-
netstat
-
netstat命令 用来打印Linux中网络系统的状态信息,可让你得知整个Linux系统的网络情况。
-
-
grep
- grep (global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。用于过滤/搜索的特定字符。可使用正则表达式能配合多种命令使用,使用上十分灵活。
-
less
- less命令 的作用与more十分相似,都可以用来浏览文字档案的内容,不同的是less命令允许用户向前或向后浏览文件,而more命令只能向前浏览。
-
tail
- 在屏幕上显示指定文件的末尾若干行
扩展知识点:
- 还有一些知识点不常考,做适当了解了即可,例如内存分页管理与swap 机制,任务队列与cpu load 等,这些知识在分析线上问题中十分有用。
- 扩展知识点
- 内存屏障
- 指令乱序
- 以上两个会在多线程的总结接触到
- 分支预测
- cpu亲和性
- Netfliter与iptables
示指定文件的末尾若干行
扩展知识点:
- 还有一些知识点不常考,做适当了解了即可,例如内存分页管理与swap 机制,任务队列与cpu load 等,这些知识在分析线上问题中十分有用。
- 扩展知识点
- 内存屏障
- 指令乱序
- 以上两个会在多线程的总结接触到
- 分支预测
- cpu亲和性
- Netfliter与iptables