Interview questions
System
- 进程和线程区别
- 进程资源分配的基本单位:有自己独立的:虚拟地址空间,打开的文件描述符、全局变量、堆
- 线程运行在进程里面,共享进程的大部分资源,只有自己的栈、寄存器、线程局部存储
- 线程更加轻量, 成本 更低
- 什么是死锁,死锁的必要条件
线程 A 拿着锁 L1 等锁 L2,线程 B 拿着锁 L2 等锁 L1。
- 互斥条件(Mutual Exclusion)
- 占有并等待条件(Hold and Wait)
- 不可剥夺条件(No Preemption)
- 循环等待条件(Circular Wait)
- 进程间通信方式
- Pipe, Socket, 消息队列,共享内存,信号量 / 互斥锁,signal
- linux系统里面是怎么设计内存分配器的?
用户态: malloc -> 调用 brk/mmap
内核态: kmalloc(小块 + 物理连续;用 SLAB/SLUB 分配器,再向 伙伴系统 要页), vmalloc(大块 + 只虚拟连续)
页分配器 (Buddy System)
当程序需要分配一大块连续的物理内存时,如果空闲内存分散成许多小块,即使总和足够,分配也会失败。这被称为外部碎片。Buddy System 必须确保大块内存能够被有效保留或恢复。
Buddy System 通过其独特的结构,使得空闲的内存块在释放时可以高效且快速地与相邻的“伙伴”块合并 (coalesce) 成一个更大的连续内存块。
Slab 分配器
要解决的问题:内部碎片 (Internal Fragmentation) 和分配开销 (Overhead)
Slab 分配器会为每种内核对象类型(如
inode结构体)维护一个专门的 缓存 (Cache)。这个缓存中预先分配了许多大小恰好的内存块(Slabs),并对其中的对象进行了预先初始化。
-
内存里的有序索引一般使用什么数据结构?
-
存在一个redis服务器集群,现在向集群中新增一个节点,怎么做数据迁移?
-
使用链表管理共享内存分配,如果一个进程A申请了一块新的内存,结果进程A挂了,怎么回收这块内存?
-
介绍一下leveldb的核心数据结构
-
你在linux上是怎么调试程序的?gdb使用?gdb是怎么查看string值
-
linux中的虚拟内存?
-
linux中为什么是三级页表?
-
TLB的作用?
-
中断为什么要分上半部和下半部?还有别的考虑吗?提示一下,考虑函数可重入性
-
你是怎么测试系统吞吐的?
-
你是怎么找到系统瓶颈的?
-
为了获取更好的程序性能,你做过数据预取、SIMD等计算机体系结构相关的优化吗?
-
讲一下CPU流水线
-
CPU进行矩阵按行遍历/按列遍历的性能差距有多少
-
介绍存算架构
-
讲一下CPU的cache line
CPU 不直接一字节一字节、甚至不是一整块数组地搬数据,而是按 固定大小的块 来搬,这个块就是 cache line。通常是 64 字节。你访问某个地址
p,CPU 实际会把p所在的那一整条 cache line读进 cache
- cache一致性协议
每个核都有 自己的 L1/L2 cache, 但大家 共享同一块物理内存
- write-through(直写):每次 CPU 写 cache 的同时也写内存
- write-back(回写):写只改 cache,把 cache line 标记为 “脏(dirty)”,等这条 line 被换出时再写回内存
MESI 是目前最常见的缓存一致性协议之一
M (Modified):已修改(脏),只有一个 cache 有它,内存是旧的
E (Exclusive):独占,内容和内存一样,只有一个 cache 有它
S (Shared):共享,内容和内存一样,可以在多个 cache 里同时存在
I (Invalid):无效,这条 line 在这个 cache 里不能用了
任何一个核要从内存拿数据,都得通过总线发一个“读事务”,这个读事务在 MESI 里就记为 BusRd
-
如何对性能瓶颈进行优化的?
-
如果没有占比较大的算子,你如何进行优化?
-
内核态和用户态的区别?什么情况会陷入到内核态?
-
有一个文件描述符,向offset=3kb处写入4MB数据,操作系统中会发生什么?
-
主存的读写时延是多少?cache 的读写时延是多少?
-
讲一下 page cache
-
什么情况下使用 page cache?什么情况下使用 direct io?
-
讲一下图数据库和关系型数据库的区别
-
系统中线程上下文开销比较大,如何解决这个问题?
-
讲一下 redis 为什么高性能?
-
系统调用是如何实现的?linux 有哪些常见的系统调用?
-
kafka相比于普通的生产者消费者的优势是什么
-
根据用户名查询权限列表时很慢,怎么排查慢SQL原因以及解决方案
-
你知道虚拟内存吗?好处是什么?每个页的大小一般是多少?
Network
- TCP三次握手
- 滑动窗口协议
- TCP释放连接中的2TSL的作用是什么
- 怎么修改UDP协议,实现可靠传输?
C++
- 虚函数的用处,实现原理
- weak_ptr和shared_ptr的区别,shared_ptr的实现原理
- shared_ptr在什么情况下会造成内存泄漏?
- 基类的析构函数要加virtual关键字吗?不加virtual会有什么后果?
- C中的static关键字
- C语言中,数组和指针的关系是什么?定义int A[10],如何不使用size/宏遍历数组?sizeof(A)是多少?
- 熟悉多线程编程吗?锁有哪几种?怎么实现的?
- C++ 11相比C++ 98新增加了哪些特性?
- STL中的 unordered_map 和 map 有什么区别?
- 知道右值引用吗?
- 对异步编程了解吗?
- 讲一下C++的多态
- 讲一下编译的过程
- 讲一下静态链接和动态链接
- C++类中默认创建的函数有哪些?
- 什么情况下要用到拷贝构造函数
- 一个class里面,模板函数可以是虚函数吗?
- 为什么模板函数体要放在.h文件里面?
- 栈上分配内存和堆上有什么区别?
- 讲一下IO多路复用,epoll原理?
- 增加删除元素,哪几种数据结构的迭代器不失效?
- hash table 冲突解决方法
- 讲一下 C++ memory 模型中的 release
- C++ 用过哪些开源的网络库?
- 介绍一下 RabbitMQ
- 网卡的混杂模式
- TCP 之前的端口被占用,TCP 怎么还有链接
- 假设一个类继承了有虚函数的类,父类会存在在子类中吗?
- 虚表里除了可能有虚函数,还可能有什么?
Coding
- LRU
- 手写 shared_ptr
- 待排序数据放在磁盘中,内存容量比较小,怎么对数据进行排序?
- 磁盘中有1TB数据,内存大小为4GB,如何对数据去重?估计运行时间是多少?
- 三个线程,线程1打印a,线程2打印b,线程3打印c。如何做到顺序打印a,b,c
- 写题:根据cas执行,写无锁list
- 在一大块连续内存上实现 hash map,主要实现出来 set(key, value) 函数
- 手撕题:找出两个有序数组的中位数
- 交易场景下,1s下单不能超过100笔,系统调用超过100笔,做拦截该如何实现?
- 手撕:实现日期类,要求支持两个日期相减