第四批 OS / 网络 / C++ 八股 · 复习总结(6 主题)
使用说明:先自测「判别规则速查表」,遮住右列自答;再做「综合练习题」,最后对答案。
面试前只翻本目录,不背题。
一、判别规则速查表(遮右自测)
| # |
主题 |
一句话判别规则 |
| 41 |
进程 vs 线程 |
要崩溃隔离/资源独立 → 进程(切换重:换地址空间);要轻快/共享数据 → 线程(切换轻、一个崩全崩);线程共享变量必须同步 |
| 42 |
僵尸/孤儿/守护进程 |
子死+父未 wait=僵尸;父先死+子活=孤儿(init 收养);主动 setsid 脱离终端=守护;ctrl+Z+bg 不算(还连终端会收 SIGHUP) |
| 43 |
TCP 如何保证可靠 |
ACK 确认 + 重传(超时/快重传)+ 序号(判重复/乱序)+ 校验(查损坏)+ 滑动窗口(接收方)+ 拥塞控制(网络);可靠是"尽力而为"非绝对 |
| 44 |
C++ struct vs class |
功能完全相同;唯一区别=默认访问权限(struct public / class private)+ 默认继承(struct public 继承 / class private 继承) |
| 45 |
C++ 构造/析构(RAII) |
构造=创建时初始化、析构=销毁时清理;RAII=栈对象自动析构(非 new/delete);移动给临时对象、拷贝给存活对象;容器默认走移动,移动不可用才拷贝 |
| 46 |
SMP/多核 |
多核=真并行(单核=并发);共享数据必须原子/锁;缓存一致性(MESI)+ 伪共享(同缓存行)是坑;关中断只关本核,多核要自旋锁 |
二、易混对比集中营(高频考点串讲)
进程 vs 线程
|
进程 |
线程 |
| 地址空间 |
独立(隔墙) |
共享(同一进程) |
| 切换开销 |
重(换页表/TLB) |
轻(换寄存器/栈指针) |
| 崩溃影响 |
崩一个不影响其他 |
一个崩 → 整个进程崩 |
| 通信 |
IPC(管道/消息/共享内存) |
共享变量 + 锁 |
僵尸 / 孤儿 / 守护
|
僵尸 |
孤儿 |
守护 |
| 谁死了 |
子死,父活 |
父死,子活 |
谁都没死 |
| 本质 |
残留 PCB 未回收 |
init 收养继续跑 |
主动脱离终端后台 |
| 处理 |
父 wait 回收 |
init 等完再回收 |
自己独立 |
僵尸三解法:父 wait() / 双 fork(孙被 init 收)/ signal(SIGCHLD, SIG_IGN)。
守护创建:fork → setsid → 再 fork(防重新获取终端)→ chdir("/") → umask(0) → close(0/1/2)。
TCP vs UDP
|
TCP |
UDP |
| 可靠 |
可靠(序号/确认/重传) |
不可靠(发了不管) |
| 连接 |
面向连接(三次握手) |
无连接 |
| 速度 |
慢(要确认) |
快(不确认) |
| 场景 |
文件/网页/邮件 |
视频直播/DNS/游戏 |
滑动窗口 vs 拥塞控制(两个窗口取最小值)
|
滑动窗口 |
拥塞控制 |
| 能力 |
接收方能力 |
网络能力 |
| 防 |
淹没接收方 |
搞崩网络 |
| 手段 |
接收方报 Window |
慢启动/拥塞避免/快恢复 |
序号 vs 校验和
|
序号(Seq) |
校验和(Checksum) |
| 作用 |
判重复/乱序 |
查数据完整性(坏了没) |
| 响应 |
丢弃重复/重排 |
丢弃损坏 |
三次握手 vs 四次挥手
|
三次握手 |
四次挥手 |
| 目的 |
建立连接 |
断开连接 |
| 次数 |
3(SYN+ACK 合并) |
4(FIN/ACK 分开,半关闭) |
| 为什么 |
防旧 SYN 浪费资源 |
全双工,一方 FIN 还能收 |
struct vs class vs union
|
struct |
class |
union |
| 默认访问 |
public |
private |
public |
| 内存 |
累加 |
累加 |
共用一块(取最大) |
| 用途 |
聚合数据 |
封装/多态 |
协议解析/类型转换 |
| 构造/析构 |
有 |
有 |
有(C++11 起) |
深拷贝 vs 浅拷贝 vs 移动
|
浅拷贝 |
深拷贝 |
移动 |
| 指针 |
复制指针值(共享) |
新分配+复制数据 |
偷指针+原对象置空 |
| 后果 |
双重释放崩溃 |
安全 |
安全且 O(1) |
| 给谁 |
禁用 |
存活的已存在对象 |
用完即弃的临时对象 |
移动构造三要素:右值引用参数 + 转移资源 + 原对象置空(防双重释放)。
移动优先原则(核心)
- 标准库容器重定位元素:默认走移动,移动不可用(
=delete/未定义/非 noexcept)才走拷贝
- 为什么 noexcept 关键:vector 扩容要强异常安全,移动可能抛异常就回退拷贝
- 推论:
std::unique_ptr(只移动不拷贝)能存 vector
- C++17 保证复制省略:
return T(); 直接构造,拷贝 =delete 也能编译(C++11/14 不行)
并行 vs 并发 / SMP vs AMP
|
并行 |
并发 |
| 定义 |
同一时刻同时执行 |
轮流切换,同一刻一个 |
| 需要 |
多核 |
单核即可 |
|
SMP |
AMP |
| 核关系 |
对等(对称) |
不等(异构分工) |
| 例子 |
普通多核 CPU |
big.LITTLE、GPU+CPU |
原子操作 vs 锁 vs 自旋锁
|
原子操作 |
锁 |
自旋锁 |
| 实现 |
硬件原子指令 |
原子指令+睡眠 |
忙等轮询 |
| 开销 |
最小 |
有切换 |
忙等耗 CPU |
| 适用 |
单变量(count++) |
多步临界区 |
多核短临界区 |
三、综合练习题(答完再对答案)
判断题(对/错 + 一句话理由)
- 浏览器一个标签页崩了,其他标签页不受影响,是因为每个标签页用了独立线程。答:
- 孤儿进程会被 init 进程"回收清除",就像僵尸被父进程 wait 那样。答:
- 一个程序用 daemon() 脱离终端后台运行,但父进程还活着——它不是守护进程,因为守护必须父进程先死。答:
- 终端里 Ctrl+Z 挂起再 bg 放到后台的进程,就是守护进程。答:
- TCP 有拥塞控制,所以 TCP 传输一定是可靠的。答:
- UDP 没有序号和确认,所以 UDP 数据包一定会丢。答:
- TCP 接收方靠校验和判断收到的包是不是重复的。答:
- C++ 里 struct 只能放数据,class 只能放方法,两者不能混用。答:
class A { int x; }; 外面写 A a; a.x = 5; 报错,改成 struct A 就能编译。答:
struct 和 class 同样的成员,sizeof 结果不同。答:
- 把
new/delete 换成 RAII 后,中途 return 时资源就一定能被释放。答:
- 移动构造是复制一份数据给新对象,所以比拷贝构造慢。答:
- 一个类声明了析构函数,编译器仍然会隐式生成移动构造函数。答:
- 多核系统里,关中断(临界区)可以保护共享数据不被其他核访问。答:
arr[0] 和 arr[100] 两个变量由不同线程各写一个,因为离得远,绝不会伪共享。答:
- 单核 CPU 上跑两个线程,它们同一时刻可以并行执行。答:
填空题
- 僵尸进程产生的原因:子进程已退出、父进程没有调用 ____ 回收。
- 孤儿进程最终由 ____(PID 1)收养,等它运行完再回收。
- 守护进程创建的关键一步是调用 ____ 创建新会话、脱离控制终端。
- TCP 用 ____ 号判断重复/乱序,用 ____ 检查数据完整性。
- TCP 靠 ____(接收方能力)和 ____(网络能力)两个窗口控制发送速度,实际取 ____ 值。
- TCP 四次挥手比三次握手多一次,是因为 FIN 和 ____ 要分开发送(半关闭状态)。
- C++ struct 默认访问权限是 ____,class 默认是 ____。
- C++ struct 默认 ____ 继承,class 默认 ____ 继承。
- 移动构造的签名是
ClassName(____),参数是右值引用。
- 移动构造三要素:右值引用参数、*、*(防双重释放)。
- 标准库容器重定位元素时默认走 ____,移动不可用时才走 ____。
- 移动构造声明为 ____ 后,vector 扩容才放心用移动(保证强异常安全)。
- C++17 的 ____(特性)让
return T(); 直接构造,无需拷贝/移动构造。
- 多核保护临界区要用 ____ 锁(忙等),不能只靠关中断。
- 伪共享的判断标准:变量地址间隔 ____(小于/大于)缓存行大小(通常 64 字节)。
场景 / 代码判断
- 场景:多个并发任务都要频繁访问同一份数据,且要求切换轻快 → 用进程还是线程?为什么线程崩会拖垮整个进程?
- 场景:父进程不关心子进程退出状态,想彻底不产生僵尸 → 给出两种方案。
- 场景:视频直播丢几帧没关系,但不能卡顿 → 用 TCP 还是 UDP?为什么不用另一个?
- 代码判断:
std::unique_ptr<int> u(new int(5)); 能不能放进 std::vector<std::unique_ptr<int>>?扩容时怎么搬?
- 场景:4 核 CPU 上两个线程分别绑核 0、核 1,同时执行
count++(共享变量)不加锁 → 结果一定对吗?为什么?
四、答案(已分离)
答案解析已单独存放,避免自测时不小心看到答案:
第四批复习总结-答案.md(同目录)——完成全部 36 题后再翻开对照。
复习目标:每条规则能自己讲出"为什么",不只记住结论。