1️⃣ Linux 是怎么实现并发的?有了进程和线程就可以实现并发了吗?

第一层:任务抽象

Linux程序执行流 抽象成 “任务”,常见表现为:

  • 进程: 资源分配的基本单位,拥有独立地址空间
  • 线程: CPU 调度的基本单位,同一进程内线程共享地址空间、文件描述符等资源

第二层:调度器

Linux 通过 调度器CPU 时间切给不同任务。

即使只有一个 CPU 核,也可以通过 时间片轮转 + 上下文切换,让多个任务 “看起来同时在运行”,这叫 并发

第三层:中断与系统调用

用户程序一旦发生:

  • 时钟中断
  • 缺页中断
  • 系统调用
    CPU 会陷入内核,内核就有机会切换任务等。

第四层:阻塞/非阻塞 + 多路复用

2️⃣ 单核 CPU 可以实现多线程吗?

  单核 CPU 上只能做到:多线程并发,不能做到真正的并行

3️⃣ 虚拟地址

  虚拟地址 是程序看到的地址,不是物理内存条上的真实地址。

4️⃣ 程序的地址空间

  • .text
  • .rodata
  • .data
  • .bss
  • heap
  • 内存映射区
  • stack
  • 内核空间

5️⃣ 虚拟内存

  虚拟内存 就是 操作系统每个进程 提供的一套“看起来连续、独立、足够大”的内存抽象。

6️⃣ 介绍一下 TCP 协议?

  • 面向连接: 通信前要先建立连接
  • 可靠传输: 通过确认 ACK、重传、校验等机制保证数据可靠到达
  • 面向字节流: 应用看到的是连续字节,不关心报文边界
  • 全双工: 双方可同时发送和接收

7️⃣ 这里 TCP 连接,所谓的连接,什么叫做连接呢?

  TCP“连接” 是指 双方在内核里建立了一份彼此认可的、可持续维护的通信状态

  • 双方 IP 和端口(四元组)
  • 当前发送/接收序号
  • ACK 状态
  • 发送窗口、接收窗口
  • 各种定时器
  • 重传状态
  • 协议选项(MSS、窗口扩大、时间戳等)

8️⃣ 建立连接以后,客户端和服务端较建立之前,有什么差异呢?内核还有什么变化呢?

建立前

  客户端和服务端双方都是 socket,没有形成一条确定的会话

建立后

  双方内核都会创建该连接对应的 TCP 控制块

  • 连接四元组
  • 状态 ESTABLISHED
  • 初始序号 ISN 和当前收发序号
  • 发送缓冲区、接收缓冲区
  • 窗口大小
  • 重传队列
  • 定时器

服务端监听 socket 后面通常还涉及两个队列:

  • 半连接队列: 收到 SYN,进入 SYN_RECV
  • 全连接队列: 三次握手完成,等待 accept

9️⃣ 所以建立连接本质上是做了什么事情呢?

  • 确认双方可达
  • 同步初始序号
  • 分配并初始化状态资源

1️⃣0️⃣ TCP 三次握手流程

1️⃣1️⃣ ACK 的值有什么作用?为什么要设成 +1 呢?

ACK 的作用?

  我已经成功收到你发来的、序号小于 ACK 的所有字节;我下一步期望收到的是 ACK 这个序号对应的数据;本质上是累计确认

为什么是 seq + 1

  因为 SYN 虽然不携带应用数据,但它本身会消耗一个序号。

为什么 SYN 要占一个序号?

  因为它也必须进入可靠传输序列空间,避免旧报文干扰新连接

1️⃣2️⃣ 那三次握手以后,这个 ACK 的值还有用吗?其他的值还有什么用?

  **有用,而且一直有用 !!!**,ACK 后续的作用:

  • 确认收到的数据
  • 驱动发送窗口滑动
  • 判断是否需要重传
  • 配合拥塞控制
  • 实现累计确认

其他值的作用

自己背

1️⃣3️⃣ TCP是如何保证有序的?

TCP 能保证有序,核心靠 序列号 + 接收端重排 + 累计确认

1️⃣4️⃣ 那它是怎么做到可以寻址的呢?

  一条 TCP 连接 通常靠 四元组 进行唯一标识 (srcIP:srcPort + dstIP:dstPort);

  • IP 层负责 “找到主机”
  • TCP 层负责 “找到主机上的哪个进程/哪个 socket

1️⃣5️⃣ 如果两次握手会怎么样?

  • 客户端无法确认服务端是否具备接收能力,也无法确认服务端收到了自己的最终确认状态,会带来状态不一致问题。
  • 旧的、延迟的 SYN 报文可能到达服务端,让服务端错误建立连接。

1️⃣6️⃣ 两次握手浪费的是哪里的资源呢?服务端还是客户端?

  主要浪费服务端资源。

1️⃣7️⃣ 建立 TCP 以后,传送包的时候,需要得到确认,才会发送下一个包吗?

  • TCP 不是 “停等协议”,不是发一个包等一个 ACK 再发下一个。
  • TCP 用的是滑动窗口:只要发送窗口内还有空间,发送方就可以连续发多个报文段,而不用等每一个都确认。

1️⃣8️⃣ TCP 建立连接的时候,是怎么确定滑动窗口大小的呢?

  • 接收窗口 rwnd 由接收方决定,表示我当前还能接收多少数据
  • 拥塞窗口 cwnd 由发送方根据网络状况维护,表示我认为当前网络最多允许我发送多少数据而不至于拥塞
  • 实际发送窗口: 发送方真正能发的数据量,通常受 min(rwnd, cwnd) 限制。

1️⃣9️⃣ 假如你信号变差了,滑动窗口会受到什么影响呢?

 &emsp“信号变差” 本质上会让链路质量下降,表现为:丢包率上升

TCP 的影响

  • 首先影响的是 拥塞窗口 cwnd,通常会变小。

虽然接收方 rwnd 可能没变,但:**发送窗口 = min(rwnd, cwnd)**,所以实际可发送的数据量也会变小,吞吐下降。

2️⃣0️⃣ send 命令调用成功是怎么保证对端收到数据?

  send 调用成功,并不代表对端已经收到。

  • 通常表示:用户态缓冲区的数据,已经成功拷贝到了内核发送缓冲区,或者已经被内核接管准备发送。
  • 它并不保证:
    • 数据已经发到网卡
    • 数据已经到达对端机器
    • 对端 TCP 已经确认
    • 对端应用已经 recv

TCP 怎么保证可靠送达? 靠的是 TCP 协议栈后续机制:

  • 数据发出去
  • 对端 TCP 收到后返回 ACK
  • 本端收到 ACK,才知道数据可靠到达对端 TCP
  • 若超时没收到 ACK,则重传