面试经验

面试题三个字给学子们带来的吸引力是超乎想象的, 因为我们都知道纯粹的理想主义在现实主义面前是那么的不堪一击. 面对浩如烟海的知识, 了解的越多我越知道我不了解的越多, 相比于完全无法证明的简历上的 "了解linux内核", 从各种意义上来看, 正确回答几个面试官问题的押宝显得多么有性价比

我知道我总是有不知道的事情, 掌握不牢的知识, 不了解的东西, 不可能面面俱到. 本文既然放在这个位置, 也算是一个总结. 对于下面的每个问题, 我只想要答案, 不想真的深挖到内核的边边角角细枝末节, you know what I mean

个人经验

字节跳动后端一面

  1. 做个自我介绍
  1. kvm 和 qemu 的区别
  1. virtio 的原理
  1. virtio 前端后端
  1. vhost 和 vhost-user
  1. dpdk 如何实现网络数据包加速的
  1. epoll 如何唤醒 fd, 是否走 virtio
  1. 内存虚拟化
  1. 问了下我的研究课题(分层内存管理)

算法题

一个有序数组 [-3,-1,0,1,3], 返回每个元素平方之后的新数组

直接排序后sort是O(nlogn)

可以先找到最接近0的,左右两边分判断大小, O(n)

二面的时候问了问项目, 当时简历上写的没什么创新点, 后面给挂了

字节网络平台一面

  1. 做个自我介绍
  1. 一台主机通过网络访问另一台主机读取/写入文件时的性能开销可能在哪里,如何优化?
    • 网络本身的延迟,带宽, 拥塞带来的影响, 启用 RDMA, 启用 压缩和去重 传输,减少数据量(如 rsync、ZFS 复制), 调整 TCP 窗口大小和缓冲区,提高吞吐量
    • NFS/SMB 额外协议负担:每次访问可能涉及额外的权限检查、元数据查询.同步写入(Sync Write):某些协议默认开启同步写入,导致每次写入都需要等待磁盘确认. 关闭不必要的同步写入(如 async 挂载 NFS)
    • 如果远程主机使用 HDD,随机 I/O 性能可能是瓶颈, 存储设备的并发 I/O 处理能力有限, 远程存储系统的缓存命中率影响读取性能. 升级到 NVMe SSD 或企业级 SSD, 启用 存储端缓存(如 NVMe-oF, LVM Cache) 来减少磁盘访问延迟. 使用 RAID 0/10 提高吞吐量,避免 RAID 5/6 带来的写入放大
    • 文件系统类型如 ext4、XFS、ZFS,不同的元数据管理方式影响性能, 选择适合大规模 I/O 的文件系统,如 XFS、ZFS、btrfs, 使用 本地缓存(如 FS-Cache、CacheFS),减少重复访问
    • 应用层避免频繁小文件操作,减少网络往返开销, 使用 aio 或 mmap 提高并发性,减少同步等待, 如使用 zstd、lz4 进行透明压缩,减少传输数据量
  1. DPU如何加速TCP/IP网络
  1. TCP的四个定时器
  1. ping www.baidu.com, 请求过程
  1. 一台裸金属服务器卖给用户之后如何回收
  1. 如何实现父子进程写入同一个文件的写入不覆盖
  1. 多个进程同时读写一个文件如何优化速度
  1. fork 发生时哪些复制哪些不复制, 父子进程直接哪些相同哪些不同

  1. 零拷贝是什么意思, 是如何实现的, 真的没有内存拷贝么
  1. 异步 IO 是如何实现的, 为什么没有广泛流行

问的太网络了而且太具体业务了, 答不出来

算法题, 输出几次 "-" ?

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
    for(int i=0;i<2;i++) {
        fork();
        printf("-");
    }
    return 0;
}

这段代码乍一看好像是输出六次, 一共循环两次, 第一次创建两个进程输出两个, 第二次变成四个进程输出四个, 一共 6 个, 但是实际运行一下就会发现输出了 8

我们先稍微修改一下代码

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
    for(int i=0;i<2;i++) {
        fork();
        printf("-\n");
    }
    return 0;
}

我们只是在输出的时候加一个换行符, 但是运行之后我们惊奇的发现输出又变成了 6 次!

这个原因和缓冲区有关, printf("-") 会将 - 写入标准输出缓冲区,但不会立即刷新(除非缓冲区满或遇到换行符 \n).如果缓冲区未刷新,子进程会继承父进程的缓冲区内容

所以实际上第一次循环创建的两个进程的缓冲区中各自有一个 "-" 但是没有输出, 第二次循环2->4之后每个进程的缓冲区内部都是 "--", 因此输出 8 次

腾讯CSIG(腾讯云)一面

算法题 单链表反转

内存管理

1.Linux系统的内存用掉了多少,还剩余多少?下面这个free命令每一个数字是什么意思?

2.为什么要有DMA、NORMAL、HIGHMEM zone?每个zone的大小是由谁决定的?

3.系统的内存是如何被内核和应用瓜分掉的?

4.底层的内存管理算法buddy是怎么工作的?它和内核里面的slab分配器是什么关系?

5.频繁的内存申请和释放是否会导致内存的碎片化?它的后果是什么?

6.Linux内存耗尽后,系统会发生怎样的情况?

7.应用程序的内存是什么时候拿到的?malloc()成功后,是否真的拿到了内存?应用程序的malloc()与free()与内核的关系究竟是什么?

8.什么是lazy分配机制?应用的内存为什么会延后以最懒惰的方式拿到?

9.我写的应用究竟耗费了多少内存?进程的vss/rss/pss/uss分别是什么概念?虚拟的,真实的,共享的,独占的,究竟哪个是哪个?

10.内存为什么要做文件系统的缓存?如何做?缓存何时放弃?

11.Free命令里面显示的buffers和cached分别是什么?二者有何区别?

12.交换分区、虚拟内存究竟是什么鬼?它们针对的是什么性质的内存?什么是匿名页?

13.进程耗费的内存、文件系统的缓存何时回收?回收的算法是不是类似LRU?

14.怎样追踪和判决发生了内存泄漏?内存泄漏后如何查找泄漏源?

15.内存大小这样影响系统的性能?CPU、内存、I/O三角如何互动?它们如何综合决定系统的一些关键性能?

进程管理

1.Linux进程和线程如何创建、退出?进程退出的时候,自己没有释放的资源(如内存没有free)会怎样?

2.什么是写时拷贝?

3.Linux的线程如何实现,与进程的本质区别是什么?

4.Linux能否满足硬实时的需求?

5.进程如何睡眠等资源,此后又如何被唤醒?

6.进程的调度延时是多少?

7.调度器追求的吞吐率和响应延迟之间是什么关系?CPU消耗型和I/O消耗型进程的诉求?

8.Linux怎么区分进程优先级?实时的调度策略和普通调度策略有什么区别?

9.nice值的作用是什么?nice值低有什么优势?

10.Linux可以被改造成硬实时吗?有什么方案?

11.多核、多线程的情况下,Linux如何实现进程的负载均衡?

12.这么多线程,究竟哪个线程在哪个CPU核上跑?有没有办法把某个线程固定到某个CPU跑?

13.多核下如何实现中断、软中断的负载均衡?

14.如何利用cgroup对进行进程分组,并调控各个group的CPU资源?

15.CPU利用率和CPU负载之间的关系?CPU负载高一定用户体验差吗?

文件系统(存储)

为什么XFS、ZFS 比ext4更适合大规模 I/O 的文件系统

🔹XFS

多线程高并发优化:

分配组(Allocation Group, AG)机制:

适用于高吞吐应用:

🔹ZFS

Copy-on-Write(COW)并行写入:

事务组(Transaction Group, TXG)优化:

内置校验和(End-to-End Checksum):

快照(Snapshot)和数据版本管理:

自动修复(Self-Healing):

参考

zood