原子、syscall 与 VFS

共 51 题
#

1. x86 TSO 的 store buffer 允许哪些重排,mfence、lock 前缀与编译器屏障分别约束什么?

A 编译器屏障会产生硬件指令
B TSO 允许任意重排
C TSO 允许 store-load 重排(store buffer 所致);mfence 是 CPU 全屏障、lock 前缀隐含全屏障、编译器屏障只约束编译器不约束 CPU ✓ 正确答案
D lock 前缀不提供屏障
#

2. Arm 的 DMB、DSB、ISB 如何区分数据排序、完成性与指令流同步?

A DMB 比 DSB 开销更大
B 三种屏障语义相同
C DMB 保证屏障前后内存访问排序(不等待完成),DSB 等待所有进行中访问完成,ISB 冲刷流水线使后续指令看到控制/代码变更 ✓ 正确答案
D ISB 管数据排序
#

3. CMPXCHG 在多核之间如何通过缓存锁与 RFO 保证原子性,LR/SC 在 x86 上为何演化为 CMPXCHG 实现?

A 原子指令总是锁总线
B lock 前缀经缓存锁(独占缓存行+一致性协议)保证原子性,跨行退化为总线锁;x86 用 CMPXCHG 因 TSO+缓存锁语义足够且无 LR/SC 伪失败 ✓ 正确答案
C LR/SC 不存在伪失败
D ARM 也使用总线锁
#

4. x86 的 clflush、clflushopt 与 clwb 在持久内存语义上的差别,clwb+sfence 为何能保证崩溃一致性?

A sfence 使数据写入非持久域
B clwb 会失效缓存行
C clflush 是异步指令
D clwb 写回但不失效缓存行,clflushopt 异步失效写回;clwb+sfence 使数据先持久、标记后发布,断电无中间态 ✓ 正确答案
#

5. LL/SC 循环为何可能伪失败,抢占、缓存一致性流量与 reservation granule 如何影响进展?

A LR/SC 的 SC 可能因抢占、缓存行迁移与 reservation granule 放大而伪失败,需退避与避免临界区切换;架构保证竞争下的弱公平 ✓ 正确答案
B SC 只在地址被写时失败
C 伪失败会永久饿死线程
D LL/SC 与缓存一致性无关
#

6. Armv8 引入 RCpc 风格的 ldapr 后,相比 ldaxr 在性能和多核扩展性上做了哪些权衡?

A ldaxr 不建立监视器
B ldapr 可以替代 CAS 循环
C ldapr 是普通 load+acquire(RCpc),不参与监视器协议、不干扰他人 LL/SC、延迟低;但不能配对 SC 做 RMW,排序域弱于 ldaxr/ldar ✓ 正确答案
D ldapr 的 acquire 语义与 ldar 完全相同
#

7. 弱一致性平台(如 POWER)上单条 ld/st 加载可能跨越 store buffer 与 cache 飞地,编译器 fence 与 CPU fence 怎样协同?

A POWER 只需 lwsync 无需编译器配合
B POWER 与 x86 排序能力相同
C 编译器 fence 会产生硬件屏障指令
D POWER 允许 store-load/store-store/load-load 等重排,需编译器 fence(保证机器码序)与 CPU fence(hwsync/lwsync,保证观察序)成对协同 ✓ 正确答案
#

8. ARMv9 的 MTE(Memory Tagging Extension)如何为内存分配打标签以检测越界与释放后使用,调试时如何解读标签不匹配?

A MTE 只检测栈溢出
B MTE 的粒度是 4KB
C MTE 标签碰撞完全不可能
D MTE 以 16B 粒度 4 位标签比对指针与内存标签,越界/释放后使用触发 tag check fault;调试看 ESR/FAR 与分配器元数据定位 ✓ 正确答案
#

9. 对引用计数采用 relaxed 增量、release 减量并在归零路径执行 acquire fence 的依据是什么?

A 归零路径的 fence 可以省略
B 增量必须 acquire
C relaxed 增量只需原子性(对象已发布),release 减量发布最后的使用,归零路径 acquire fence 与 release 配对建立 hb,防止释放后使用 ✓ 正确答案
D release 减量使对象字段不可见
#

10. 当无锁计数从 32 位扩展到 128 位(cmpxchg16b/ldaxp-stxp)时,对齐约束为何决定 ABI 兼容性?

A cmpxchg16b 不需要对齐
B cmpxchg16b/ldaxp-stxp 要求 16 字节对齐,对齐决定结构偏移与 sizeof,故 128 位原子成员的 ABI 布局必须跨编译器一致并静态断言 ✓ 正确答案
C 128 位原子在任何平台都无锁
D 对齐只影响性能不影响 ABI
#

11. 编译器在 -O3 下可能把两个相邻 release store 合并为一次,带来的可观察性问题与硬件 fence 缺失有何关联?

A C++ 允许编译器合并相邻原子 store(除非 volatile),依赖中间值的两步发布会被破坏;这是编译层消除,与硬件 fence 缺失的 CPU 重排是两类问题 ✓ 正确答案
B 编译器禁止合并任何原子操作
C release store 保证中间值可见
D 合并与硬件 fence 是同一问题
#

12. 在用户态实现自旋等待时,使用 pause/yield/rep nop 指令分别在功耗、流水线压力与等待粒度上有何差异?

A 自旋等待与缓存行争用无关
B yield 的响应比裸自旋更快
C pause 增加功耗
D pause 微停顿降功耗降流水线压力且粒度仍细,yield 让出时间片功耗最低但粒度粗有调度延迟;短等待用 pause、长等待应睡眠 ✓ 正确答案
#

13. 大小核(big.LITTLE)异构调度下不同核心的内存序实现是否一致,迁移线程会否影响无锁代码的可观察行为?

A 小核的内存序与大核不同
B 大小核共享一致性域且遵循同一 ISA 内存模型,无锁语义不因核而异;迁移只影响缓存局部性等性能,除非代码隐式依赖每核状态 ✓ 正确答案
C 迁移会破坏已建立的 release/acquire 关系
D 大小核不共享缓存一致性
#

14. errno 为什么是线程局部状态,系统调用返回值与 libc 错误约定如何转换?

A errno 是线程局部状态(glibc 中为 TLS 宏 __errno_location),避免多线程错误码互污染;内核返回负 rax,libc 转存 errno 并返回 -1 ✓ 正确答案
B errno 是全局变量
C 内核返回正 errno
D errno 在成功调用时也会被设置
#

15. ELF 程序启动时内核、动态链接器、crt 与 main 的调用链如何衔接?

A _start 用 C 语言编写
B 动态链接器在 main 之后运行
C 内核 exec 映射程序与 ld.so 并布置栈与 auxv;ld.so 加载依赖重定位后跳 AT_ENTRY(_start);crt 经 __libc_start_main 初始化后调用 main ✓ 正确答案
D 辅助向量与启动无关
#

16. 在多线程进程中 fork 后立即 exec,线程局部 errno、pthread_key 析构与 atfork 处理为何需要被显式管理?

A 子进程中所有线程的 TLS 都被析构
B fork 复制所有线程
C fork 只复制调用线程,其他线程的锁在子进程冻结可能死锁;TLS/errno 继承调用线程,键值析构只对调用线程执行,需 atfork 钩子修复 ✓ 正确答案
D atfork 钩子在子进程只执行一次 prepare
#

17. 程序在容器内报告 EMFILE 时,如何区分进程 RLIMIT_NOFILE、systemd 限制与全局文件表压力?

A 提高 fs.file-max 即可解决所有 EMFILE
B EMFILE 是全局文件表压力
C systemd 不能设置 rlimit
D EMFILE 是进程 fd 达 RLIMIT_NOFILE(systemd LimitNOFILE 可设置),ENFILE 是全局达 fs.file-max;用 /proc/pid/limits、fd 计数与 file-nr 分层排查 ✓ 正确答案
#

18. 当 sysctl 内核参数 fs.file-max 调高但 systemd LimitNOFILE=4096 仍在生效,应如何在进程和单元两侧同时排查?

A 调高 file-max 会自动提高进程 rlimit
B fs.file-max 是系统全局上限、LimitNOFILE 是进程 rlimit,两者叠加;用 /proc/pid/limits 看生效值,改 unit 后需 daemon-reload 并 restart ✓ 正确答案
C systemd 配置对运行中进程立即生效
D 进程 soft 限制高于 file-max 即可
#

19. 使用 LD_PRELOAD 拦截系统调用时,遇到静态链接二进制、内联 vDSO 调用与 clone3() 时拦截为何失败?

A LD_PRELOAD 能拦截所有系统调用
B LD_PRELOAD 靠动态符号解析替换 PLT 调用,静态链接无解析、vDSO 直调与 libc 内部 clone3 直 syscall 都绕过,需 seccomp/ptrace 等机制 ✓ 正确答案
C 静态二进制也走动态符号解析
D vDSO 调用经过 libc PLT 可被替换
#

20. systemd socket activation 如何在服务启动前接受连接,LISTEN_FDS 协议如何避免描述符误用?

A LISTEN_PID 用于指定端口号
B 服务启动前的连接会丢失
C systemd 先创建监听 socket,连接在内核队列排队,激活时经"fd 从 3 起 + LISTEN_FDS 计数 + LISTEN_PID 校验"协议传给服务 ✓ 正确答案
D 传递的 fd 不需要 CLOEXEC
#

21. prctl(PR_SET_NAME) 与 pthread_setname_np 在进程名和线程名显示上有何差异,/proc/self/comm 与 /proc/self/task/<tid>/comm 谁限制长度?

A 线程名与进程名是不同机制
B comm 是内核每线程字段(TASK_COMM_LEN=16,最长 15 字符);prctl(PR_SET_NAME) 与 pthread_setname_np 都设置线程 comm,进程名即主线程 comm ✓ 正确答案
C /proc/pid/comm 无长度限制
D pthread_setname_np 不经过内核
#

22. 为什么在 Linux 上 systemd unit 启动的进程退出码 143 表示被 SIGTERM,但容器内的进程退出码与宿主机可能不同?

A docker stop 总是返回 143
B 内核直接返回 128+signal
C 143=128+SIGTERM 是 shell/systemd 的退出码约定(内核只返回 wait 状态);容器内受 PID1 信号转发与 shell 包装影响,退出码可能与宿主不同 ✓ 正确答案
D 容器退出码与宿主机永远一致
#

23. sockets 单元通过 FileDescriptorName 暴露 fd 时,子进程继承顺序与 close-on-exec 标记如何被 systemd 自动处理?

A fd 编号与名字无关
B 注入 fd 从 3 起按 unit 配置顺序编号,LISTEN_FDNAMES 一一对应,服务按名字取 fd;systemd 不设 CLOEXEC(服务 exec 后需用),服务 fork 子进程时应自行关闭或置 CLOEXEC ✓ 正确答案
C systemd 自动为注入 fd 设置 CLOEXEC
D 注入 fd 只存在一次激活
#

24. Linux VFS 中 inode、dentry、file 和 super_block 分别表示什么,多个文件描述符如何共享偏移?

A inode 保存打开偏移
B 所有 fd 共享同一偏移
C inode 是文件元数据对象、dentry 是路径缓存、file 是打开描述(含偏移)、super_block 是挂载实例;dup/fork 共享同一 file 故共享偏移,独立 open 各自 file ✓ 正确答案
D dentry 保存文件内容
#

25. rename 在同一文件系统内保证何种原子性,跨文件系统为何返回 EXDEV?

A EXDEV 表示权限不足
B 跨文件系统 rename 也是原子的
C rename 会移动数据块
D 同文件系统内 rename 只改目录项与链接计数,是原子的;跨文件系统需复制数据+建新 inode+删源(非原子),VFS 返回 EXDEV ✓ 正确答案
#

26. 硬链接与软链接在 inode 引用、跨文件系统能力和目录权限传播上有哪些本质差异?

A 硬链接可跨文件系统
B 硬链接是同一 inode 的多个目录项(共享元数据、不可跨 fs、不可链目录);软链接是存路径的独立 inode(可跨 fs、可链目录、权限跟随目标) ✓ 正确答案
C 软链接的权限独立生效
D 硬链接有自己的权限
#

27. 文件描述符、打开文件描述与 inode 三个数据结构之间的关系,dup/dup2/fcntl(F_DUPFD_CLOEXEC) 如何操作它们?

A fd 级标志存于 file 中
B dup 创建新的 file
C fd 是进程表项、file 是打开会话(偏移/flags/引用计数)、inode 是对象本体;dup 使多 fd 共享同一 file(共享偏移),F_DUPFD_CLOEXEC 原子置 CLOEXEC ✓ 正确答案
D inode 保存 f_pos
#

28. fsync、fdatasync、syncfs 与目录 fsync 分别覆盖哪些持久化范围?

A fsync 刷数据+全部元数据,fdatasync 只保证数据持久,syncfs 同步整个文件系统;目录 fsync 保证目录项(rename/create)在崩溃后存在 ✓ 正确答案
B fdatasync 也刷全部元数据
C rename 后只需 fsync 文件
D 目录 fsync 无意义
#

29. O_DIRECT 绕过页缓存后,对齐、长度和并发映射的限制分别是什么,与 O_SYNC 的语义叠加会带来哪些性能影响?

A O_DIRECT 与 O_SYNC 叠加无性能影响
B O_DIRECT 不需要对齐
C O_DIRECT 要求缓冲/偏移/长度块对齐,I/O 期间用户页被固定;叠加 O_SYNC 后每次写都要等待持久完成且无写回聚合,吞吐显著下降 ✓ 正确答案
D O_DIRECT 页可以随意回收
#

30. 为什么 NFS 客户端对 rename 的语义并不完全等同于本地文件系统,NFSv4 的 close-to-open 一致性具体指什么?

A NFS rename 与本地一样立即可见
B NFS 与本地文件系统语义完全一致
C CTO 保证并发读写实时一致
D NFS 操作在服务端执行但客户端有属性/目录缓存,视图弱一致且受缓存滞后影响;close-to-open 保证关闭后打开前看到最新数据(close 时 flush/commit) ✓ 正确答案
#

31. copy-on-write 文件系统(如 Btrfs、ZFS)的快照与写时复制如何影响块分配,与日志型文件系统相比的事务边界有何差异?

A COW 文件系统覆盖写原块
B COW 修改时分配新块并逐级更新树指针,快照/克隆共享未改块(引用计数),崩溃恢复靠树根原子发布无需重做日志;日志 fs 靠 journal 重放 ✓ 正确答案
C 日志文件系统不需要额外写放大
D 快照必须复制全部数据
#

32. 容器卷绑定 bind mount 时出现的 lowerdir/upperdir/workdir 三层 overlay 与普通 mount 在 VFS 路径解析上有何不同?

A overlay 只有一层
B bind mount 是同一子树在 VFS 的别名(同一 super_block);overlayfs 是 upper+lower 多树合成,upper 优先查找、写 lower 触发 copy-up、删除用 whiteout ✓ 正确答案
C bind mount 创建新文件系统
D overlay 的 lower 层可写
#

33. 使用 fallocate(FALLOC_FL_PUNCH_HOLE) 在稀疏文件中打洞时,文件系统如何确保范围不出现未初始化读取?

A PUNCH_HOLE 解除范围块映射并裁剪部分覆盖的边界块,打洞后范围读必为零(空洞语义),一致性由锁与日志/COW 保证 ✓ 正确答案
B 打洞后范围读返回旧数据
C 打洞不需要 extent 拆分
D 打洞与并发 I/O 保证原子
#

34. glibc 包装函数、vDSO 与真实系统调用路径有何差异,哪些时间函数通常可避免陷入内核?

A 所有时间函数都必须系统调用
B vDSO 仍然需要进入内核
C vDSO 是内核映射的用户态代码页,gettimeofday/clock_gettime 等无状态时间查询可免系统调用执行;其余操作经 glibc 包装走真实 syscall ✓ 正确答案
D strace 能观测到 vDSO 调用
#

35. 系统调用入口从 int 0x80 到 syscall/sysenter 的演进如何减少模式切换开销,vDSO 的 AT_SYSINFO_EHDR 由谁填充?

A AT_SYSINFO_EHDR 由 glibc 生成
B syscall 与 int 0x80 开销相同
C int 0x80 走中断门保存完整现场最慢,sysenter 用 MSR 轻量切换,syscall/sysret 现场保存最少最快;AT_SYSINFO_EHDR 由内核 exec 时填充指向 vDSO ✓ 正确答案
D sysenter 需要 IDT 查表
#

36. seccomp-BPF 与 seccomp-BPF+libseccomp 在过滤策略表达力和 syscall 参数检查上有何工程取舍?

A libseccomp 能读取指针内容
B seccomp 可以检查字符串路径内容
C seccomp-BPF 只能过滤 syscall 号与参数寄存器值(不能读指针内容),手写需防架构绕过;libseccomp 封装提供跨架构映射与架构守卫,表达力相同但更安全易用 ✓ 正确答案
D seccomp-BPF 无动作可返回
#

37. ptrace 与 strace 的实现区别是什么,自定义 tracer 在 PTRACE_EVENT_* 上需要做哪些系统调用重放?

A strace 基于 ptrace 的 PTRACE_SYSCALL 进出停读寄存器实现;自定义 tracer 用 PTRACE_O_TRACE* 处理 fork/exec/exit 事件,并在 syscall-stop 修改寄存器实现重放/注入 ✓ 正确答案
B strace 不用 ptrace
C PTRACE_EVENT_FORK 时子进程自动被跟踪
D tracer 不能修改返回值
#

38. 辅助向量 AT_RANDOM、AT_PLATFORM、AT_HWCAP 各自提供给运行时哪些启动信息,常见安全特性开关如何使用?

A AT_RANDOM 提供 exec 时随机数(canary 初始化),AT_PLATFORM 提供平台字符串,AT_HWCAP/HWCAP2 提供 CPU 特性位图供 ifunc/安全特性(CET/MTE)开关 ✓ 正确答案
B AT_RANDOM 是命令行参数
C AT_HWCAP 只用于显示
D 安全特性开关与 auxv 无关
#

39. atime、mtime、ctime 三种时间戳分别在何种系统调用下被更新,相对挂载选项(relatime、noatime)如何影响其刷新策略?

A stat 调用会更新 atime
B ctime 是创建时间
C atime 由读更新、mtime 由内容修改更新、ctime 由 inode 状态变更更新;relatime 仅在 mtime/ctime 更新后或超 24 小时刷 atime,noatime 完全不刷 ✓ 正确答案
D noatime 下读也会写元数据
#

40. Java Unsafe.putObjectVolatile 与 VarHandle.setRelease 在底层屏障选择上为何不同,哪种更适合 lazySet?

A putOrderedObject/lazySet 只保证 store-store 有序与最终可见(不参与发布-获取),setRelease 建立完整 release 语义;发布数据必须用 setRelease ✓ 正确答案
B lazySet 与 release 语义相同
C putOrdered 保证读者立即看到
D setRelease 不需要与 acquire 配对
#

41. glibc 的 NPTL 与 musl 在线程栈默认值、信号栈大小与取消栈处理上的差异如何影响嵌入式部署?

A 两 libc 的取消语义完全相同
B musl 默认栈也是 8MB
C NPTL 默认栈随 ulimit(通常 8MB),musl 固定 128KB 更适合内存受限多线程;取消点与信号栈处理实现不同,深递归需显式加大栈 ✓ 正确答案
D musl 不提供 sigaltstack
#

42. ulimit 设置 hard/soft 时进程运行时提升 hard 是否会跨越登录会话,pam_limits 与 systemd 的覆盖关系是什么?

A systemd 服务也经 pam_limits 设置
B 提升 hard 会全局生效
C soft 可在 hard 内自调,提升 hard 需特权且只影响本进程链(经 fork 继承,不跨登录会话);systemd 服务走 Limit* 指令、登录会话走 pam_limits,两套路径各自生效 ✓ 正确答案
D 普通用户可任意提升 hard
#

43. 环境变量、auxiliary vector 和命令行参数在初始用户栈上如何布局,各自适合传递什么信息?

A argc 在栈底最低地址
B auxv 可以被环境变量伪造
C envp 由内核直接生成
D 初始栈自上而下为字符串区、auxv、envp、argv、argc;argv 传执行输入、env 传可继承配置、auxv 传内核可信启动信息(不继承、不可伪造) ✓ 正确答案
#

44. systemd unit 的 Requires、Wants、Requisite、PartOf 在依赖失败时的级联行为分别如何?

A Requires 是强依赖(启动失败级联且运行中依赖失败会停本 unit),Wants 尽力启动无传播,Requisite 只检查已激活,PartOf 在组主单元停止时连带停止 ✓ 正确答案
B Wants 失败也会级联
C Requisite 会主动启动依赖
D PartOf 影响启动依赖
#

45. RISC-V 的 RVWMO 与 x86-TSO 在允许的内存重排范围上有何差异,移植无锁代码时需要补充哪些屏障?

A RVWMO 与 TSO 相同
B TSO 只允许 store-load 重排,RVWMO 允许 load-load/store-store 等多向重排;移植时 acquire/release 需映射为 lr.aq/sc.rl 或 fence,可用 fence.tso 获得 TSO 强度 ✓ 正确答案
C x86 的 release 也需要显式指令
D RISC-V 无需屏障即可移植
#

46. 使用 Type=notify、Type=dbus、Type=exec 与 watchdog 的 systemd 服务在启动完成语义上有什么区别?

A watchdog 决定启动完成
B Type=notify 不需要 sd_notify
C simple/exec 以进程启动即完成,forking 以父进程退出为完成,notify 等服务发 READY=1 才完成,dbus 以总线名注册为完成;watchdog 是运行期心跳机制 ✓ 正确答案
D Type=exec 等待业务就绪
#

47. Unix domain socket 的路径名与抽象命名空间在生命周期、权限和可移植性上有何差别?

A 抽象命名空间也创建 socket 文件
B 路径名 socket 是文件系统对象(有残留需 unlink、可设文件权限、跨 POSIX);抽象命名空间无文件对象(进程退出即消失、无文件权限、Linux 特有) ✓ 正确答案
C 路径名 socket 自动清理
D 抽象名可被 chmod 控制
#

48. 环境变量值在 setuid 程序中被自动过滤的机制是什么,LD_LIBRARY_PATH 等危险键位为何被清空?

A 环境过滤只针对 root
B setuid 程序仍信任 LD_PRELOAD
C 内核在 exec 时以 AT_SECURE 标记特权过渡,ld.so/glibc 进入安全模式忽略 LD_PRELOAD/LD_LIBRARY_PATH 等注入向量;setuid 程序应用 secure_getenv ✓ 正确答案
D AT_SECURE 由用户设置
#

49. 实现特权分离守护进程时,应在何时完成 bind、chroot、setgroups、setuid 与能力裁剪?

A 能力裁剪应在最开始时做
B setuid 后再 setgroups 也可以
C chroot 后无需 chdir
D 先完成特权操作(bind 特权端口、读配置),再 chroot(后 chdir /)、setgroups 必须在 setuid 前、组后用户、最后裁剪能力并设 no_new_privs ✓ 正确答案
#

50. systemd 的 user 实例与 system 实例在 cgroup、journal 写入和 socket 命名空间上的差别,如何选择正确的 bus?

A user 实例与 system 实例共享 cgroup 根
B user 实例管理 user-<uid>.slice 下的 cgroup、日志进用户 journal、socket 在 $XDG_RUNTIME_DIR(权限 700);系统服务连系统总线、用户服务连 $XDG_RUNTIME_DIR/bus ✓ 正确答案
C journalctl 无法区分用户日志
D 用户总线与系统总线互通
#

51. 应用采用临时文件加 rename 更新配置时,怎样保证断电后既不丢文件内容也不丢目录项?

A 正确序列为写临时文件→fsync 临时文件→rename→fsync 父目录:内容先持久再发布目录项,任一点断电都得到完整旧版或完整新版 ✓ 正确答案
B rename 后无需 fsync 目录
C 先 fsync 目录再 fsync 文件更安全
D 临时文件可与目标不同文件系统