面试总结专题

用户态到内核态转换

操作系统的进程空间可分为用户空间和内核空间,它们需要不同的执行权限。其中系统调用运行在内核空间。
从用户态切换到内核态主要有如下几种方式:
1.系统调用
在电脑中,系统调用(英语:system call),指运行在用户空间的程序向操作系统内核请求需要更高权限运行的服务。系统调用提供用户程序与操作系统之间的接口。大多数系统交互式操作需求在内核态运行。如设备IO操作或者进程间通信。

2.异常
页缺失(英语:Page fault,又名硬错误、硬中断、分页错误、寻页缺失、缺页中断、页故障等)指的是当软件试图访问已映射在虚拟地址空间中,但是目前并未被加载在物理内存中的一个分页时,由中央处理器的内存管理单元所发出的中断。
通常情况下,用于处理此中断的程序是操作系统的一部分。如果操作系统判断此次访问是有效的,那么操作系统会尝试将相关的分页从硬盘上的虚拟内存文件中调入内存。而如果访问是不被允许的,那么操作系统通常会结束相关的进程。
虽然其名为“页缺失”错误,但实际上这并不一定是一种错误。而且这一机制对于利用虚拟内存来增加程序可用内存空间的操作系统(比如Microsoft Windows和各种类Unix系统)中都是常见且有必要的。

3.中断
中断是用以提高计算机工作效率、增强计算机功能的一项重要技术。最初引入硬件中断,只是出于性能上的考量。如果计算机系统没有中断,则处理器与外部设备通信时,它必须在向该设备发出指令后进行忙等待(Busy waiting),反复轮询该设备是否完成了动作并返回结果。这就造成了大量处理器周期被浪费。引入中断以后,当处理器发出设备请求后就可以立即返回以处理其他任务,而当设备完成动作后,发送中断信号给处理器,后者就可以再回过头获取处理结果。这样,在设备进行处理的周期内,处理器可以执行其他一些有意义的工作,而只付出一些很小的切换所引发的时间代价。后来被用于CPU外部与内部紧急事件的处理、机器故障的处理、时间控制等多个方面,并产生通过软件方式进入中断处理(软中断)的概念。

进程间通信

进程间通信
每个进程各自有不同的用户地址空间,当进程间需要同步数据时,需要先将数据从用户空间拷贝到内核缓冲区,另一个进程再从内核缓冲区把数据拷走,内核提供的这种机制称为进程间通信(IPC,InterProcess Communication)。

管道/匿名管道(pipe)
命名管道(FIFO)
信号(Signal)
消息队列
共享内存
信号量
套接字

go协程模型

简单来说协程是一种用户态、编程语言层面的轻量级线程。线程是靠操作系统OS本身来调度,是抢占式的任务处理方式,线程切换成本较高,因此需要控制线程数。

协程拥有用户态的上下文和栈,协程切换相对于线程切换非常轻量。协程本质是单线程,适合计算密集型。
协程也叫用户态线程,协程之间的切换发生在用户态。在用户态没有时钟中断,系统调用等机制,那么协程切换由什么触发?调度器将控制权交给某个协程后,控制权什么时候回到调度器,从而调度另外一个协程运行? 实际上,这需要协程主动放弃CPU,控制权回到调度器,从而调度另外一个协程运行。所谓协作式线程(cooperative),需要协程之间互相协作,不需要使用CPU时将CPU主动让出。

linux性能优化

性能分析工具

系统级工具有top sar vmstat netstat pstack strace perf
常用的四个高性价比工具top pstack strace perf

top命令

top命令可以简单直观地看到CPU 内存等几个关键的性能指标。
按M按照从大到小对内存占用(RES/MEM)排序
按P按照从大到小队CPU占用排序
可以使用组合键xb使用<和>选择需要进行排序的列,这样更灵活,不用单独记如何排序内存和CPU.

pstack命令

pstack命令可以打印进程的调用栈信息,有点像进程的某一时刻的快照,如果反复执行pstack显示的堆栈相同,说明这里可能存在性能问题。

strace命令

strace命令可以显示进程当前正在执行的系统调用,把pstack和strace命令结合起来就能知道进程在用户空间和内核空间大致做了哪些事情。进而可以分析存在性能瓶颈的地方。
不过,有的时候,你也可能会“一无所获”,毕竟这两个工具获得的信息只是“表象”,数据的“含金量”太低,做不出什么有效的决策,还是得靠“猜”。要拿到更有说服力的“数字”,就得 perf 出场了。

perf命令

我常用的 perf 命令是“perf top -K -p xxx”,按 CPU 使用率排序,只看用户空间的调用,这样很容易就能找出最耗费 CPU 的函数。比如,下面这张图显示的是大部分 CPU 时间都消耗在了 ZMQ 库上,其中,内存拷贝调用居然达到了近 30%,是不折不扣的“大户”。所以,只要能把这些拷贝操作减少一点,就能提升不少性能。

源码级工具

top、pstack、strace 和 perf 属于“非侵入”式的分析工具,不需要修改源码,就可以在软件的外部观察、收集数据。它们虽然方便易用,但毕竟是“隔岸观火”,还是不能非常细致地分析软件,效果不是太理想。
在这里,我要推荐一个专业的源码级性能分析工具:Google Performance Tools,一般简称为 gperftools。它是一个 C++ 工具集,里面包含了几个专门的性能分析工具(还有一个高效的内存分配器 tcmalloc),分析效果直观、友好、易理解,被广泛地应用于很多系统,经过了充分的实际验证。
它的用法也比较简单,只需要在源码里添加三个函数:
ProfilerStart(),开始性能分析,把数据存入指定的文件里;
ProfilerRegisterThread(),允许对线程做性能分析;
ProfilerStop(),停止性能分析。
所以,你只要把想做性能分析的代码“夹”在这三个函数之间就行,运行起来后,gperftools 就会自动产生分析数据。
gperftools工具安装方法:

./autogen.sh
./configure
make -j8
sudo make install
ldconfig 

序列化

序列化主要有json protobuf msgpack,详细介绍参考15.序列化:简单通用的数据交换格式有哪些?