秋招才刚开始,原则上是不应该放面经的。我个人十分不赞成投机取巧,知识面狭窄的问题,绝非面经能够解决,有时可能适得其反。
无奈的是应该有不少实验室做的研究和业界(客气点说)实在不太对口,相信大家在内推阶段或多或少的遇到过类似的困扰,面试不好并不是我平时偷懒,而是因为面试官只问他们感兴趣的/擅长的,对于自己不懂的,总有那么一点“不屑一顾”的感觉。
我的个人经历证实,这些情况确实是存在的,大多数面试官还是会尝试让你去解释研究工作(虽然对方并不一定感兴趣),只不过此时更多考察个人的表述能力。
从7月初到9月初,各大公司的优招、内推,我基本都参加了,投递岗位涉及编译器开发、服务架构、基础平台研发(网络、存储)等,该拿的offer基本都到手了,所以稍作总结,如果你也是这个方向的,相信是具有一定的参考意义的。
问题大致涵盖如下方面:
- 基本算法
- Linux命令的使用
- 操作系统(着重)
- 网络(着重)
- 数据库
- 编译技术
- 分布式
面试基本会涉及如下几个环节:
- 自我介绍
- 手撸代码(通常是一面)
- 领域问题考察
- 项目细节考察
- 系统设计题(通常是架构岗)
现场要求写的代码都很简单(不知道是不是我遇到的比较简单),涉及一些递归、DP等,不会难于LC的middle级别,所以LC刷个200+就基本没问题了。
基本算法方面考察的主要是算法的应用场景,时间复杂度等,如果是C++相关岗位,可能会涉及一些STL中的数据结构,所以难免会遭遇红黑树。另外,由于B树和B+树在数据库中应用的较多,亦有可能考到。
遇到不会的问题很正常,关键看你怎么回答。若能够跟着面试官的节奏走最好,若是似懂非懂的状态,不要太坦诚,可以把你知道的完整地跟面试官解释一遍,按着自己的节奏走,这样就不会太尴尬了。
如果遇到的全是不会的问题,那么有2种可能:
- 你投错岗位了
- 你遇到了压力面(压力面当然可以出现在技术面中)
面试过程,更多的是一种技术交流,所以遇到不会的问题,最好请对方给一个答案。另外,你需要清楚,通过面试的关键并不是你回答对了多少题目,而是环比其他面试者,你的表现能排第几,能否挤进HC,当然前提是性格、智商和逻辑都没问题。。。
接下来给出领域问题,绝大多数问题只是大致回答,懒得详细阐述了,答案存在问题是难免的。
Linux使用
查看内存信息
free/vmstat/top/htop
查看磁盘信息
iostat
查看CPU信息
vmstat/top/htop
查看网络信息
netstat -i 网卡信息
netstat -a 连接信息
lsof -i:PORT 查看端口占用信息
proc目录的实现原理
procfs,内部使用sysctl实现
gdb调试,线程信息,线程栈
info stack/bt 调用栈
info threads 线程信息
thread id 切换线程
watch expr 监控指定表达式
buffer、cache和total的含义
IO写入时存放数据的内存page buffer
IO读取时存放数据的内存page cache
操作系统
进程和线程的区别
对于Linux内核而言,区别并不是很大。
进程的隔离级别更加高,可以使用命名空间等,IPC的代价稍大。
线程间共享进程的地址空间,所以数据交互更容易,代价也稍小,但是数据竞争更加严重,且一旦进程crash,所有线程也就不存在了。
进程切换所做的事情
保存寄存器现场
切换栈空间
处理内存页(最好深入一下)
线程同步机制
互斥锁、自旋锁、读写锁、条件变量
列举进程通讯的方式
PIPE、共享内存、Socket、文件、MQ等
其中共享内存最快,但是需要额外的工作才能保证数据的一致性
命名空间及其效果
UTS、IPC、PID、NS、NET、USER
cgroup的功能
限制CPU和内存的使用量/使用频率
VFS文件系统
磁盘中数据的存放
IO调度算法
为何需要IO调度?结合机械硬盘的工作原理,随机读写开销很大,因此可以通过汇总数据的方式实现顺序读写。
Anticipatory算法、Deadline算法、CFQ算法以及Noop(No Operation)算法
NOOP算法是最简单的IO调度算法,适合SSD,只需要将IO请求入队列即可。
虚拟地址、物理地址及其实现
进程中可见的地址是虚拟地址,物理地址对应真实的内存,虚拟地址通过MMU映射成物理地址,Linux采用的是4级页表(PGD、PUD、PMD、PTE),最终对应到CR3寄存器。
转换的方式为基址+“偏移”,由于页表保存在内存中,CPU访存代价过大,因此引入TLB缓存,每次映射时优先查找TLB。
网络
TCP状态图,结合握手和挥手
注意同时打开和同时关闭即可,其余结合TCP状态转移图进行理解。
异常状态的出现场景以及解决方案
大量SYN_RECV状态的连接,大量TIME_WAIT状态的连接等。
长连接和短连接
短连接:数据请求到达后即关闭连接
长链接:多次请求复用一次连接,需要清楚如何保证连接是否存活,如心跳信号等。
TIME_WAIT的等待时间,MSL的意思
MSL(Maximum Segment Lifetime)
TIME_WAIT后并不能保证最终的ACK能够安全到达对端,因此需要预留重传的时间,即等待2MSL。
可以通过SO_REUSEADDR规避2MSL的等待。
RTT如何估计
RTT(Round-Trip Time)
通过计时器获取连接的一次往返时间消耗,之后还有RTT估计器的计算,细节部分参考《TCP/IP详解 卷1》。
开启SO_REUSEADDR后可能会出现什么问题
可能接收到对端传回的FIN、RST等,造成莫名其妙的问题。
TCP如何保证其可靠性
重传机制、流量控制、拥塞控制
IP序号重合对上层的影响
由IP层负责在组包时解决,对上层无影响。
内核如何解决accept的惊群问题
使用了WQ_FLAG_EXCLUSIVE标记,确保只有一个进程会被唤醒。
用户态如何解决accept的惊群问题
多进程抢占自旋锁即可,使用pthread_spinlock或者共享内存+CAS自行实现。
进一步讨论,如何在这个阶段提供负载均衡。
数据库
面试官说我不懂数据库,所以问得很少。。。
悲观锁和乐观锁
SQL中如何使用锁
索引的实现方式和作用
加快数据检索的速度,但是写入时有相应的代价,所以适合读多写少的场景。
内存通常使用B+树实现。
编译相关
解释器和编译器
常见的误区:所谓编译,并非一定要求生成本地代码,只要从语言A转换到语言B,这个过程就是编译。
编译的流程
预处理-词法解析-文法解析-语义制导-抽象语法树(IR的一种)-三地址码(SSA)-优化(控制流图、数据流图)-汇编
动态链接库和静态链接库的区别
虚拟机如何重新加载脚本
关于热更新的讨论
分布式存储
redis、rockdb、leveldb的存储布局
SSD和HDD的区别使用场景
机械结构:主控+多FLASH芯片 vs 电机+磁盘+磁车
延迟:SSD的延迟至少比HDD低1个数量级
寿命:SSD的寿命主要由P/E次数决定,因此适合多读少写的环境
其实,对于顺序读写,hdd的开销也不是那么大,原因自己去计算,另外此处可以结合IO调度算法一起考察。
锁和MVCC的适用场景
视场景而定,如果数据竞争少,则优先使用MVCC,否则老老实实用锁。
HDFS的读写操作
metadata、membership的管理
etcd或者zookeeper,真的很方便哦~
副本一致性(RSM)
通过一致性算法,如Paxos、2PC、3PC、Raft等
主从使用push和pull的优缺点
主节点push可以保证一致性,如果无需考虑一致性,则从节点pull更加灵活,可以支持更多的从节点
虽然和主题不相关,但我还是想说,棒棒哒!
虽然看不懂,,但我还是想说,棒棒哒!
好几篇文章和自己最近做的看的相近,就是没找到博客订阅在哪。
博客系统本身是支持feed的,只不过我在做主题时把显式的按钮给去除了,可以试试/feed路径。