# 1. mmap 与 read/write 在页缓存利用与数据复制次数上的性能差异从何而来? A mmap 直接映射页缓存减少一次数据复制,read/write 需用户态与内核态间复制 ✓ 正确答案 B read/write 比 mmap 复制次数更少 C mmap 无法共享页缓存 D 两者性能完全相同
# 2. mprotect 与 mlock 的使用场景是什么,RLIMIT_MEMLOCK 如何限制锁定内存? A mprotect 锁定内存 B mlock 修改访问权限 C mprotect 修改访问权限,mlock 锁定内存防换出,RLIMIT_MEMLOCK 限制可锁定总量 ✓ 正确答案 D 锁定内存无任何限制
# 3. 多个进程/线程 epoll 同一 listen fd 时,新连接到来会唤醒所有等待者(惊群),EPOLLEXCLUSIVE 如何保证只唤醒一个? A EPOLLEXCLUSIVE 会唤醒所有等待者 B EPOLLEXCLUSIVE 使内核只唤醒一个等待者,避免 accept 惊群 ✓ 正确答案 C EPOLLEXCLUSIVE 可与 EPOLLONESHOT 同时使用 D EPOLLEXCLUSIVE 用于普通数据 fd
# 4. IORING_OP_SPLICE 在零拷贝管道传输中为何要求一端为 pipe,且对文件类型与偏移有哪些限制? A splice 总是复制数据,无法零拷贝 B splice 可用于任意文件到文件复制 C splice 至少一端为管道,依赖页缓存借用实现零拷贝,文件类型与偏移有限制 ✓ 正确答案 D splice 对偏移无限制
# 5. BPF 验证器的抽象解释如何追踪寄存器与栈状态,从而保证程序安全终止与内存安全? A 验证器不追踪指针边界 B 验证器在运行期检查内存 C 验证器允许无限循环 D 验证器用抽象解释追踪寄存器/栈状态与指针边界,保证循环有界与内存安全 ✓ 正确答案
# 6. BTF 与 CO-RE(Compile Once – Run Everywhere)如何实现跨内核版本免重编译? A BTF 与字段偏移无关 B CO-RE 需要为每个内核版本重编译 C BTF 描述类型布局,CO-RE 通过运行时重定位修正字段偏移,跨内核免重编译 ✓ 正确答案 D CO-RE 只支持固定内核布局
# 7. select 每次调用都要把 fd_set 从用户态拷入内核并在返回后重置,这一开销在大连接数下为何显著? A select 每次调用拷贝整个 fd_set 并线性扫描,大连接数下开销显著 ✓ 正确答案 B select 只处理活跃 fd,开销恒定 C select 的 fd_set 大小可无限增长 D select 在大连接数下优于 epoll
# 8. epoll 的 EPOLLONESHOT 使一次就绪只被一个线程处理,它如何避免多线程下同一 fd 被并发处理? A EPOLLONESHOT 允许同一 fd 被多线程并发处理 B EPOLLONESHOT 使事件持续触发 C EPOLLONESHOT 使事件触发一次后自动禁用,需重新注册,避免多线程并发处理同一 fd ✓ 正确答案 D EPOLLONESHOT 无需重新注册
# 9. select 受 FD_SETSIZE(通常 1024)限制且编译期固定,这给运维带来什么不便? A select 对 fd 数量无上限 B FD_SETSIZE 可在运行时调整 C select 的 FD_SETSIZE 编译期固定(通常 1024),高并发下需重编译或改用 epoll ✓ 正确答案 D fd 超过 FD_SETSIZE 时 select 安全忽略
# 10. madvise 的 MADV_SEQUENTIAL/RANDOM/WILLNEED 提示如何影响内核预读与回收策略? A MADV_WILLNEED 回收已读页 B 三个提示效果完全相同 C MADV_RANDOM 加大预读 D MADV_SEQUENTIAL 加大预读并回收已读页,MADV_RANDOM 关闭预读,MADV_WILLNEED 主动预读 ✓ 正确答案
# 11. EPOLLEXCLUSIVE 与 SO_REUSEPORT 各自在什么层面缓解惊群?两者能否叠加使用? A SO_REUSEPORT 使多进程竞争同一 accept B 两者都只在唤醒层作用 C 两者互斥,不能同时使用 D EPOLLEXCLUSIVE 缓解唤醒层惊群,SO_REUSEPORT 缓解连接分发层惊群,可叠加 ✓ 正确答案
# 12. signalfd、timerfd、eventfd 把信号、定时器、事件计数都转化为可读文件描述符,它们如何与 epoll 统一进同一事件循环,替代传统信号处理与 setitimer? A 三者只能单独使用,不能加入 epoll B 三者把信号、定时器、事件计数转化为可读 fd,可与 epoll 统一事件循环 ✓ 正确答案 C signalfd 无需先阻塞信号 D timerfd 无法与 epoll 结合
# 13. 不同内核版本支持的 io_uring 操作码不同,应用如何用 IORING_REGISTER_PROBE 探测可用 opcode 并优雅回退到 epoll/系统调用? A 探测失败应直接崩溃 B io_uring 在所有内核支持全部 opcode,无需探测 C 用 IORING_REGISTER_PROBE 探测 opcode,不支持的走回退路径(epoll/系统调用),并做抽象层 ✓ 正确答案 D io_uring 无法与 epoll 共存
# 14. IORING_OP_READV/WRITEV 相比直接调用 preadv/pwritev 的性能优势主要来自哪些被省去的路径开销? A io_uring 无法批量提交 B io_uring 每次操作都需一次 syscall C io_uring 比 preadv 多一次数据拷贝 D io_uring 通过共享内存环形队列批量提交,减少 syscall 次数与参数拷贝 ✓ 正确答案
# 15. eBPF helper call 与 map 操作受到哪些安全性约束,verifier 如何限制指针算术? A verifier 不限制指针算术 B BPF 程序可调用任意内核函数 C helper 只能调用内核白名单函数,verifier 追踪指针类型与边界限制指针算术 ✓ 正确答案 D map 操作无任何约束
# 16. select 用固定大小的 fd_set 位图、poll 用 pollfd 数组,两者在 fd 数量增长时为何都是 O(n) 扫描? A select/poll 复杂度与 fd 数无关 B select/poll 只扫描就绪 fd C epoll 也全量扫描所有 fd D select/poll 无状态,每次全量扫描所有 fd,复杂度 O(n);epoll 有状态只返回活跃 fd ✓ 正确答案
# 17. epoll 用红黑树管理注册 fd、用就绪链表返回事件,为什么 epoll_wait 的耗时只与活跃 fd 数相关而非总数? A epoll_wait 遍历所有注册 fd B epoll_wait 只返回就绪链表中的活跃 fd,耗时与活跃数相关而非总数 ✓ 正确答案 C epoll 用红黑树直接返回就绪事件 D epoll_wait 耗时与注册总数线性相关
# 18. epoll 如何通过内核回调(ep_poll_callback)将就绪 fd 挂入就绪链表,从而缓解 C10K 问题? A ep_poll_callback 与就绪链表无关 B epoll 每次都全量扫描 fd C fd 就绪时内核回调 ep_poll_callback 把事件挂入就绪链表,epoll_wait 只取活跃事件,缓解 C10K ✓ 正确答案 D epoll 无法处理万级连接
# 19. 为什么说 poll 本身只有水平触发语义,用 poll 模拟边沿触发需要应用自行记录并比较前后就绪状态? A poll 只在状态跳变时通知一次 B poll 原生支持边沿触发 C poll 只有水平触发,持续就绪持续返回,模拟 ET 需应用记录并比较前后状态 ✓ 正确答案 D poll 的 ET 由内核提供
# 20. MAP_SHARED 与 MAP_PRIVATE 在写时复制与回写语义上有何区别,各自的典型用途是什么? A MAP_PRIVATE 的修改会写回文件 B MAP_SHARED 共享页且可回写,MAP_PRIVATE 用 COW 私有副本,不改写文件 ✓ 正确答案 C MAP_SHARED 的修改只对当前进程可见 D 两者在写语义上完全相同
# 21. mmap 的 MAP_ANONYMOUS 与文件映射在来源与用途上有何不同,MAP_FIXED 为何危险? A MAP_FIXED 安全,不会覆盖已有映射 B MAP_ANONYMOUS 无文件源,MAP_FIXED 强制覆盖指定地址已有映射(危险),可用 MAP_FIXED_NOREPLACE 替代 ✓ 正确答案 C MAP_ANONYMOUS 基于文件页缓存 D MAP_FIXED 让内核自动选择地址
# 22. mmap 映射文件后被 truncate 或访问超出文件尾的页为何触发 SIGBUS? A mmap 后文件大小变化不影响访问 B 这种情况触发 SIGSEGV C truncate 后访问超出文件尾的映射页无法从磁盘填充,触发 SIGBUS ✓ 正确答案 D SIGBUS 表示地址不合法
# 23. msync 与 munmap 如何控制修改回写与映射解除,MS_SYNC 与 MS_ASYNC 的差别是什么? A MS_ASYNC 保证数据已落盘 B MS_SYNC 同步等待回写完成,MS_ASYNC 异步回写,MAP_SHARED 修改需 msync 才可靠持久化 ✓ 正确答案 C munmap 自动回写所有修改 D MAP_PRIVATE 的修改会被 msync 回写
# 24. 用 signalfd 接收信号前为何要先用 sigprocmask/pthread_sigmask 阻塞该信号?否则会发生什么? A 使用 signalfd 前须先阻塞信号,否则信号触发默认处理(如 SIGTERM 杀进程) ✓ 正确答案 B signalfd 无需阻塞信号 C 阻塞信号后 signalfd 读不到信号 D 未阻塞时信号进入 signalfd 队列
# 25. CQE 返回 -ENOSYS/-EOPNOTSUPP 意味着什么?运行时回退策略应如何设计? A -ENOSYS/-EOPNOTSUPP 表示内核能力缺失,应回退到系统调用/epoll 路径,而非重试 ✓ 正确答案 B 遇到 -ENOSYS 应无限重试 C -EOPNOTSUPP 表示临时失败,稍后重试 D 回退无需保证语义一致
# 26. IORING_OP_TIMEOUT 与 IORING_OP_LINK_TIMEOUT 分别用于全局超时与为链式操作设置超时,典型使用场景是什么? A 两者完全等价 B IORING_OP_TIMEOUT 用于批次/全局超时,IORING_OP_LINK_TIMEOUT 为链上前置操作设置超时 ✓ 正确答案 C LINK_TIMEOUT 用于全局超时 D TIMEOUT 无法与链式操作配合
# 27. 同一 BPF 程序挂在 socket filter 与 XDP 钩子上的性能差异从何而来? A socket filter 在 XDP 之前执行 B XDP 在驱动层、协议栈之前执行,路径更浅,避免协议栈开销,性能更高 ✓ 正确答案 C 两者执行位置完全相同 D socket filter 性能高于 XDP
# 28. 在指令数上限下如何用 tail call 与子程序拆分大型 BPF 程序? A 用子程序(bpf_call)复用代码、用 tail call(bpf_tail_call)分阶段跳转,突破指令数上限 ✓ 正确答案 B tail call 创建新栈帧 C 子程序无法降低指令数 D 只能单程序,无法拆分
# 29. 水平触发(LT)只要 fd 就绪就持续通知,边沿触发(ET)只在状态跳变时通知一次,两者编程模型有何区别? A ET 会持续通知就绪 B LT 持续通知就绪,ET 仅在状态跳变通知一次,ET 要求读尽数据直到 EAGAIN ✓ 正确答案 C LT 只需一次通知即可 D 两者编程模型完全相同