3. MAC层核心功能:调度器设计原理,HARQ重传机制,随机接入过程(RACH)

好,咱们今天聊聊MAC层最核心的三个功能模块。说实话,这三个东西搞明白了,你对基站协议栈的理解就及格了。我当年刚入行时,光一个调度器就啃了两个月,后来才发现——嗯,其实核心思想没那么玄乎。

3.1 调度器设计原理

调度器是MAC层的“大脑”。它决定谁在什么时候、用什么资源发数据。说白了,就是管分配。

我个人习惯把调度器分成两类:上行调度下行调度。下行调度好理解——基站说了算,想给谁发就给谁发。上行调度就麻烦点,你得先知道用户有数据要发,然后才能分配资源。

调度器的核心目标有三个:

  • 公平性——不能老让一个用户占着资源
  • 吞吐量——系统总速率要尽量高
  • 时延——特别是URLLC业务,延迟必须低

这三个目标其实是互相打架的。你追求吞吐量,就可能牺牲公平性。你照顾时延,吞吐量就会掉。所以调度器本质上是个多目标优化问题

3.1.1 经典调度算法

我列几个常用的,你们感受一下:

算法 核心思想 适用场景
Round Robin 轮流来,每人一次 公平性要求高,业务量均匀
Max C/I 谁信道好就给谁 追求最大吞吐量
PF (Proportional Fair) 兼顾公平和吞吐量 最常用,商用基站标配

PF算法我得多说两句。它的公式很简单:

优先级 = 当前速率 / 历史平均速率

你想想看,如果一个用户信道一直很好,历史平均速率就高,优先级反而会降下来。这就给了信道差的用户机会。我在项目中遇到过,有些团队直接用Max C/I,结果边缘用户永远抢不到资源——用户体验极差。

我的建议:商用系统中,PF算法是首选。但要注意调整遗忘因子——这个参数控制历史速率的衰减速度,直接影响调度行为的“记忆长度”。

3.1.2 调度器的实现架构

调度器在代码里通常是个事件驱动的模块。每个TTI(传输时间间隔)触发一次调度决策。我习惯把它拆成三层:

  1. 输入层——收集CQI、BSR、优先级等信息
  2. 决策层——运行调度算法,生成资源分配结果
  3. 输出层——生成DCI(下行控制信息)或UL Grant

这里有个坑——我曾经在决策层里直接操作全局变量,结果多线程调度时出了竞态条件。后来改成消息队列,问题就解决了。

注意:调度器是实时性要求最高的模块之一。在5G NR中,调度周期可以短到0.5ms。代码里千万别用锁,用无锁队列或者原子操作。

3.2 HARQ重传机制

HARQ,全称是混合自动重传请求。说白了,就是“如果数据传错了,再传一次”。但它的巧妙之处在于——不是简单重传,而是把新传和重传的数据合并起来解码。

为什么会这样?因为无线信道有衰落。第一次传可能被深衰落打中,第二次传时信道可能变好了。你把两次的软比特信息合并,解码成功率就高很多。

3.2.1 两种HARQ模式

3GPP定义了两种:

  • CC (Chase Combining)——重传时发同样的数据,接收端做最大比合并
  • IR (Incremental Redundancy)——重传时发不同的冗余版本,接收端做码字合并

IR的效率更高,但实现复杂。我建议在信道条件差的场景用IR,信道好的场景用CC就够了。

3.2.2 HARQ进程管理

每个UE有多个HARQ进程。比如LTE是8个进程,NR是16个。为什么是16个?因为NR的时延要求更低,需要更多的并行进程来“流水线”操作。

进程的状态机是这样的:

空闲 → 激活(发送初传) → 等待ACK → 
  ├─ 收到ACK → 空闲
  └─ 收到NACK → 重传 → 等待ACK → ...(最多重传4次)

我曾经在调试时发现,某个UE的HARQ进程一直卡在“等待ACK”状态。查了半天,原来是物理层没把ACK反馈送上来——嗯,接口时序没对齐。

避坑指南:HARQ的软缓冲区大小要算清楚。特别是IR模式,每个进程都要存一份软比特。内存不够的话,性能会急剧下降。

3.3 随机接入过程(RACH)

随机接入,是UE和基站建立连接的“第一握手”。UE刚开机,或者从空闲态回来,它不知道基站的时序,也不知道自己的上行同步——所以得先“喊一声”。

RACH分两种:

  • 基于竞争的——多个UE可能同时发,会冲突
  • 基于非竞争的——基站指定资源,不会冲突

大部分场景用的是基于竞争的。流程分四步:

  1. Msg1:UE发前导码(Preamble)——就是一段特定的序列
  2. Msg2:基站回RAR(随机接入响应)——告诉UE你的时序调整量、上行授权
  3. Msg3:UE发RRC连接请求——带上自己的身份信息
  4. Msg4:基站回冲突解决——确认谁成功了

这里有个细节——Msg1的发送时机。UE不知道基站的时序,所以前导码要在一个特定的时频资源上发。这个资源叫PRACH时隙

关键点:前导码的检测是基站的物理层做的。MAC层只负责配置PRACH资源和处理RAR。所以MAC和PHY的接口设计要特别小心——我曾经见过因为接口消息格式没对齐,导致RAR一直解不出来。

3.3.1 随机接入的触发条件

不是只有开机才做RACH。以下情况也会触发:

  • 上行失步——UE长时间没发数据,时序漂移了
  • SR(调度请求)失败——UE有数据要发,但没拿到上行授权
  • 切换——UE从一个基站切到另一个基站

我记得有一次,某个UE频繁触发RACH,导致网络负载飙升。查了半天,发现是UE的TA(时序提前)定时器设置得太短——还没到时间就认为失步了。

注意:RACH的冲突概率和负载成正比。如果小区里同时有大量UE做随机接入,冲突率会急剧上升。这时候可以考虑增加PRACH时隙的密度,或者用非竞争接入来分流。

3.4 三个功能的协同

调度器、HARQ、RACH不是孤立的。它们之间有很多交互:

  • RACH成功后,调度器要给UE分配初始资源
  • HARQ重传时,调度器要预留资源给重传
  • 调度器做决策时,要考虑HARQ进程的状态

我习惯在代码里用一个全局状态表来管理这些信息。每个UE一行,记录它的HARQ进程状态、调度优先级、RACH状态等。这样三个模块查起来都方便。

好了,这一章就到这里。调度器、HARQ、RACH这三个东西,你搞清楚了,MAC层的大框架就立起来了。下一章我们聊聊MAC层的其他功能——比如BSR、PHR、DRX这些。嗯,到时候再细说。