POSIX 内存管理与 mmap

共 29 题
#

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 两者编程模型完全相同