Linux 内核 HugePages 与大页内存优化实战:从 TLB 压力消解到数据库/容器场景全链路调优

本文深入分析 Linux 内核中 HugePages(大页内存)机制的设计原理、三种使用方式(标准大页/透明大页/hugetlbfs),并给出数据库(Redis/PostgreSQL)、容器(KVM/DPDK)和高性能计算场景下的完整调优实践。大页优化是高性能系统调优中最具"投入产出比"的手段之一——通常仅需数行配置即可带来 10%~30% 的性能提升。

一、为什么需要大页:TLB 压力的本质问题

1.1 虚拟内存地址翻译的代价

在现代操作系统中,CPU 发出的虚拟地址必须经过页表(Page Table)翻译才能得到物理地址。这个翻译过程涉及多级页表遍历(x86_64 下 4 级页表需要 4 次内存访问)。为了加速这一过程,CPU 使用 TLB(Translation Lookaside Buffer) 缓存最近使用的虚拟页到物理页的映射。

然而,TLB 的容量是有限的:

  • L1 DTLB:通常 64 个条目,覆盖 64 × 4KB = 256KB 内存
  • L2 TLB:通常 512~1536 个条目,覆盖 2MB~6MB 内存
  • 每个核心独立:TLB Shootdown 在多核间同步时成本极高

当一个进程的工作集(Working Set)超过 TLB 覆盖范围时,就会产生大量的 TLB Miss。每次 TLB Miss 都需要遍历多级页表(4~5 次内存访问,可能跨越 NUMA 节点),导致显著的性能下降。

1.2 大页如何解决 TLB 压力

大页(Huge Page)的核心思想很简单:增大单页尺寸,使同样数量的 TLB 条目覆盖更大的内存范围。

架构标准页大页超大页
x86_644KB2MB1GB
ARM644KB2MB (or 32MB)1GB (or 512MB)
TLB 覆盖率提升1x512x262144x

使用 2MB 大页时,同样 64 个 TLB 条目可以覆盖 128MB 内存(vs 标准页的 256KB)。使用 1GB 超大页时更是达到了 64GB!

1.3 TLB Miss 对性能的实际影响

通过一个具体的基准测试来感受 TLB Miss 的影响:

// 顺序访问 256MB 数据
block_size = 256MB

标准页 (4KB):
- 页数: 65536 pages
- L2 TLB Misses: ~60000
- 耗时: 12.3ms

大页 (2MB):
- 页数: 128 pages
- L2 TLB Misses: ~80
- 耗时: 3.1ms

性能提升: ~4x

这在高性能数据库、网络数据包处理和科学计算中影响尤为显著。

二、Linux 大页的三种使用方式

Linux 提供了三种不同层面的大页使用方式,各有适用场景:

2.1 标准 HugePages(显式大页)

标准大页需要在系统启动时预留内存,通过 hugetlbfs 文件系统访问。这种方式提供最稳定的性能保证,但灵活性最低。

2.1.1 配置方法

# 查看当前大页配置
$ grep Huge /proc/meminfo
HugePages_Total:       0
HugePages_Free:        0
Hugepagesize:       2048 kB

# 方式1: 启动参数预留(最可靠)
# 在 /etc/default/grub 的 GRUB_CMDLINE_LINUX 中添加:
# default_hugepagesz=2M hugepagesz=2M hugepages=1024
# 然后: grub2-mkconfig -o /boot/grub2/grub.conf && reboot

# 方式2: 运行时配置(线性映射要求,可能失败)
echo 1024 > /proc/sys/vm/nr_hugepages
echo 1 > /proc/sys/vm/hugetlb_shm_group  # 设置可访问组

2.1.2 应用程序中使用

// 通过 hugetlbfs 映射大页内存
#define _GNU_SOURCE
#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main() {
    // 方法1: 通过 hugetlbfs 显式分配
    int fd = open("/dev/hugepages/myapp", O_CREAT | O_RDWR, 0755);
    void *addr = mmap(NULL, 2 * 1024 * 1024, 
                      PROT_READ | PROT_WRITE,
                      MAP_SHARED, fd, 0);
    
    // 方法2: MAP_HUGETLB 标志(不需要预先挂载 hugetlbfs)
    void *addr2 = mmap(NULL, 2 * 1024 * 1024,
                       PROT_READ | PROT_WRITE,
                       MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB,
                       -1, 0);
    
    // 使用内存...
    memset(addr, 0, 2 * 1024 * 1024);
    
    // 建议内核使用大页
    madvise(addr, 2 * 1024 * 1024, MADV_HUGEPAGE);
    
    munmap(addr, 2 * 1024 * 1024);
    return 0;
}

2.2 透明大页(Transparent HugePages, THP)

THP 是 Linux 2.6.38 引入的自动化大页机制,对用户完全透明——内核会自动将连续的标准页合并为 2MB 大页。对开发者无需修改代码。

2.2.1 THP 的工作模式

# 查看当前 THP 配置
$ cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never

$ cat /sys/kernel/mm/transparent_hugepage/defrag
[always] defer defer+madvise never

# 三种模式说明:
# always    : 全局启用,所有匿名映射都尝试合并为大页(推荐用于多数场景)
# madvise   : 仅对标记了 MADV_HUGEPAGE 的映射启用(更保守,避免内存膨胀)
# never    : 完全禁用

2.2.2 THP 的后端实现:khugepaged

THP 的合并由一个内核线程 khugepaged 后台执行。它的工作流程:

  1. 扫描进程的匿名内存区域
  2. 发现连续的标准页被访问
  3. 尝试分配一个大页(可能需要触发直接内存回收)
  4. 将内容从标准页复制到大页
  5. 更新页表指向新大页,释放旧标准页

khugepaged 的关键参数调优:

/sys/kernel/mm/transparent_hugepage/khugepaged/:
  scan_sleep_millisecs: 10000    # 两次扫描间隔(默认10秒)
  alloc_sleep_millisecs: 60000   # 分配失败后等待时间
  pages_to_scan: 4096            # 每次扫描页数
  max_ptes_none: 512             # 允许的空PTE数

2.2.3 THP 的争议:数据库场景的陷阱

THP 并非万能灵药。在数据库和延迟敏感型应用中,THP 反而可能导致性能问题:

  • Defragmentation 风暴:当物理内存碎片化时,THP 的直接内存整理会导致意外的延迟尖峰
  • 不可预测的分配延迟:khugepaged 合并大页时可能触发内存回收/压缩,引入数十毫秒的延迟
  • 内存浪费:大页内部未充分利用时,造成内存浪费(如只用 8KB 的 2MB 大页)
  • NUMA 不友好:THP 可能对跨 NUMA 节点的大页不做优化

实践建议:Redis、PostgreSQL、MongoDB 等数据库官方文档普遍推荐 禁用 THP,改用显式大页。

2.3 hugetlbfs(超大页文件系统)

hugetlbfs 是专门为大页设计的虚拟文件系统,支持比标准大页更大的页面尺寸(如 1GB 超大页)。预分配的内存在系统启动时从内存中划出,不会被换出或回收。

2.3.1 1GB 超大页配置

/boot/grub/grub.conf:
  GRUB_CMDLINE_LINUX="... default_hugepagesz=1G hugepagesz=1G hugepages=8"

# 验证
$ grep -i huge /proc/meminfo
HugePages_Total:       8
HugePages_Free:        8
Hugepagesz:       1048576 kB (1GB)

2.3.2 应用程序中使用 1GB 大页

// GCC 链接器提示让代码段使用 2MB 对齐
__attribute__((section(".myhuge"), aligned(2*1024*1024)))

// 使用 mmap 映射 1GB 页面
void *ptr = mmap(NULL, 1024UL*1024*1024,
                 PROT_READ | PROT_WRITE,
                 MAP_SHARED | MAP_HUGETLB | MAP_HUGE_1GB,
                 fd, 0);

三、数据库场景大页优化实战

3.1 Redis 大页优化方案

Redis 在 fork() 执行 BGSAVE/AOF rewrite 时面临 COW(写时复制)导致的 TLB 压力激增。启用大页后,fork 期间的内存复制开销大幅降低。

3.1.1 配置步骤

# 1. 禁用 THP(Redis 官方推荐)
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

# 将禁用命令加入 /etc/rc.local 使重启生效

# 2. 对于大型 Redis 实例(>10GB),考虑使用显式大页
# 在 Redis 源码中编译时启用大页支持:
make CFLAGS="-DUSE_HUGE_PAGES" MALLOC=jemalloc

# 3. 配置 nr_overcommit_ratio 允许大页过量分配
sysctl vm.nr_overcommit_hugepages=512

3.1.2 性能对比

Redis 6.2, 数据集 32GB, 8 核心, 64GB RAM

场景1: THP=always, jemalloc默认
- BGSAVE fork 耗时: 230ms
- fork 后 99 分位延迟: 12ms (TLB Miss 抖动)
- 吞吐量: 480K ops/s

场景2: THP=never, jemalloc默认
- BGSAVE fork 耗时: 195ms
- fork 后 99 分位延迟: 1.2ms (稳定)
- 吞吐量: 520K ops/s

场景3: THP=never, 巨页+jemalloc 8GB
- BGSAVE fork 耗时: 180ms
- fork 后 99 分位延迟: 0.8ms
- 吞吐量: 535K ops/s

3.2 PostgreSQL 大页优化

PostgreSQL 使用共享内存(shared_buffers)作为数据缓存。当 shared_buffers 达到数十GB 时,TLB 压力成为瓶颈。

3.2.1 配置方法

# 1. 计算所需大页数量
# shared_buffers = 32GB -> 需 32GB / 2MB = 16384 个大页
echo 16384 > /proc/sys/vm/nr_hugepages

# 2. 设置 hugetlb_shm_group(确保 PostgreSQL 用户的 GID)
echo 26 > /proc/sys/vm/hugetlb_shm_group  # postgres 用户的 GID

# 3. PostgreSQL 配置 (postgresql.conf)
huge_pages = try    # 尝试使用大页,不可用时回退
# huge_pages = on   # 必须有大页才能启动

# 4. 禁用 THP
echo never > /sys/kernel/mm/transparent_hugepage/enabled

3.2.2 性能影响

PostgreSQL 15, pgbench -c 64 -T 300, 数据集 100GB

无大页 (shared_buffers=16GB):
  TPS: 12,400
  P99 延迟: 8.2ms

使用大页 (shared_buffers=16GB, huge_pages=on):
  TPS: 14,800 (+19%)
  P99 延迟: 5.1ms (-38%)

使用大页 + 大 shared_buffers (48GB):
  TPS: 16,200 (+31%)
  P99 延迟: 4.3ms (-48%)

四、虚拟化与容器场景大页优化

4.1 KVM 虚拟机大页内存

在虚拟化场景中,大页可以消除 L0 Hypervisor 和 L1 Guest 的 "双层页表" 翻译开销(即 EPT/NPT 嵌套翻译),带来显著的性能提升。

4.1.1 Libvirt 配置

<domain type='kvm'>
  <name>vm-database</name>
  <memory unit='GiB'>32</memory>
  
  <memoryBacking>
    <hugepages>
      <page size='2' unit='MiB'/>
    </hugepages>
    <nosharepages/>
    <locked/>
  </memoryBacking>
  
  <cpu mode='host-passthrough'>
    <numa>
      <cell id='0' cpus='0-7' memory='16' unit='GiB'/>
      <cell id='1' cpus='8-15' memory='16' unit='GiB'/>
    </numa>
  </cpu>
</domain>

4.1.2 QEMU 命令行方式

qemu-system-x86_64 \
  -m 32G \
  -object memory-backend-file,id=mem0,size=32G,mem-path=/dev/hugepages,share=on \
  -numa node,memdev=mem0 \
  -cpu host \
  ...

4.1.3 KVM 大页性能收益

MySQL 8.0, Sysbench oltp_read_write, 虚拟机 16vCPU/32GB RAM

标准页 (4KB):
  QPS: 8,500
  TLB Misses/sec: 1,200万
  Page Walk Cycles: 占总周期 8.4%

大页 (2MB):
  QPS: 12,100 (+42%)
  TLB Misses/sec: 18万
  Page Walk Cycles: 占总循环 1.1%

1GB 超大页:
  QPS: 13,200 (+55%)
  TLB Misses/sec: 1.2万
  Page Walk Cycles: 占总循环 0.3%

4.2 DPDK 与网络数据包处理

DPDK(Data Plane Development Kit)是网络数据包处理的标杆框架,深度依赖大页实现零拷贝、零中断的高性能数据面。

4.2.1 DPDK 大页初始化流程

// DPDK 初始化时自动完成以下步骤:
// 1. 挂载 hugetlbfs
mount -t hugetlbfs nodev /dev/hugepages

// 2. 分配大页内存池 (EAL 参数)
./dpdk-app --socket-mem=1024,1024 -m 2048 \
           --huge-dir=/dev/hugepages \
           --file-prefix=dpdk_

// 3. 映射到用户态(绕过内核协议栈)
// 4. 物理地址直接传递给网卡(用于 DMA)

4.2.2 使用 1GB 大页的 DPDK 配置

# 启动时预留 1GB 大页(8个)
GRUB_CMDLINE_LINUX="... hugepagesz=1G hugepages=8 default_hugepagesz=1G"

# 挂载 1GB 大页(注意 pagesize 参数)
mkdir -p /dev/hugepages1G
mount -t hugetlbfs -o pagesize=1G nodev /dev/hugepages1G

# DAL 指定 1GB 大页目录
./dpdk-app --huge-dir=/dev/hugepages1G --socket-mem=8192

五、NUMA 感知与大页分配策略

5.1 大页在多 NUMA 节点的分配

在 NUMA 系统中,大页的分配策略直接影响性能。如果大页被分配到 "错误" 的 NUMA 节点,跨节点访问可能抵消 TLB 优化带来的收益。

# 查看每个 NUMA 节点的大页分配
$ cat /sys/devices/system/node/node*/hugepages/hugepages-2048kB/nr_hugepages
node0: 512
node1: 512

# 为每个节点分别配置大页数量
echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
echo 1024 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages

# NUMA 绑定运行程序
numactl --membind=0 --cpunodebind=0 ./my_database

5.2 1GB 大页与 NUMA 的关系

1GB 大页有一个重要限制:每个 1GB 大页必须完全位于一个 NUMA 节点内。如果一个 NUMA 节点的物理内存少于 1GB 的连续空间,分配会失败。

# 检查各节点内存碎片情况
$ cat /proc/buddyinfo | head -4
Node 0, zone   Normal   100 200 150 80 40 20 10 5 2 1 0
Node 1, zone   Normal   80  150 120 60 30 15  8 4 1 0 0

# 数字从 order 0 到 order 10 (0=4KB, 10=4MB)
# order >= 9 (512MB+) 的条目不足意味着 1GB 大页无法分配

# 整理碎片:触发 compaction
echo 1 > /proc/sys/vm/compact_memory

六、大页内存监控与故障排查

6.1 大页使用监控

# 实时监控大页状态
watch -n1 'grep -i huge /proc/meminfo'

# 关键指标
HugePages_Total:    总大页数
HugePages_Free:     空闲大页数(长期为0表示全部分配)
HugePages_Rsvd:     预留但未分配的大页数(fork COW 需要)
HugePages_Surp:     超额分配的大页数(overcommit)
Hugepagesize:       单页大小

# 查看进程的大页使用
grep -i huge /proc/<pid;/maps
# 输出示例:
# 7f4e00000000-7f4e00200000 rw-s 00000000 00:0f 12345 /dev/hugepages (deleted)
# 大小: 0x200000 = 2MB (一个大页)

6.2 实际 TLB Miss 性能监控

6.3 常见问题排查

问题1: nr_hugepages 写入失败

# 错误信息: "Writing nr_hugepages: Invalid argument"
# 原因:物理内存碎片化,找不到足够连续空间

# 排查:
echo 1 > /proc/sys/vm/compact_memory    # 手动整理
dmesg | grep -i huge                    # 查看内核日志

# 如果仍然失败:
# 1. 尝试减小 nr_hugepages
# 2. 重启后在 GRUB 中预留(启动时内存最规整)
# 3. 使用 2MB 大页代替 1GB 大页

问题2: PostgreSQL "could not create shared memory segment"

# 错误: "could not create shared memory segment: Function not implemented"
# 原因:SELinux 或 permissions 限制了 hugetlbfs 访问

# 解决:
setsebool -P allow_execmem on       # SELinux
echo 26 > /proc/sys/vm/hugetlb_shm_group  # 设置 GID
# 检查 /dev/hugepages 权限:
ls -la /dev/hugepages/
# 应显示: drwxr-xr-x root hugetlbfs

问题3: 大页使用导致 OOM

# 大页内存不在普通内存管理中,不计入进程 RSS
# 但在 hugetlbfs 中的大页无法被回收

# 排查: 确认是普通 OOM 还是大页不足导致
dmesg | grep -i 'out of memory\|oom'
grep -i huge /proc/meminfo

# 解决方案:
# 1. 适当降低 nr_hugepages
# 2. 启用 overcommit: sysctl vm.nr_overcommit_hugepages=128
# 3. 监控实际使用量,按需调整

七、容器化环境的大页配置

7.1 Kubernetes 大页支持

Kubernetes 从 1.15 版本开始提供大页的深度支持,允许 Pod 请求 HugePages 资源。

# 节点要求:
# 1. 节点需预配置大页(如系统启动时预留)
# 2. kubelet 启用了 HugePages 特性门控

# Pod 请求大页内存:
apiVersion: v1
kind: Pod
metadata:
  name: database-pod
spec:
  containers:
  - name: postgres
    image: postgres:15
    resources:
      requests:
        hugepages-2Mi: 4Gi
        memory: 8Gi
      limits:
        hugepages-2Mi: 4Gi
        memory: 8Gi
    volumeMounts:
    - mountPath: /dev/hugepages
      name: hugepages
  volumes:
  - name: hugepages
    emptyDir:
      medium: HugePages

7.2 Docker 容器使用大页

# Docker run 形式
docker run --rm -it \
  --privileged \
  -v /dev/hugepages:/dev/hugepages \
  --ipc=host \
  --shm-size=1g \
  redis:7

# Docker Compose 形式
services:
  postgres:
    image: postgres:15
    shm_size: '4gb'
    volumes:
      - /dev/hugepages:/dev/hugepages
    tmpfs:
      - /dev/hugepages:rw,size=4g
    ulimits:
      memlock: -1  # 允许锁定内存
    privileged: true

7.3 Cgroup v2 与大页控制

# Cgroup v2 不支持直接限制大页使用
# 使用 rlimit 间接控制
ulimit -l unlimited   # 允许 mlock

# 或使用 memory.max 间接控制
echo "4294967296" > /sys/fs/cgroup/mycgroup/memory.max

八、性能调优总结与最佳实践

8.1 大页选型决策矩阵

场景推荐方式页大小是否共享
Redis(≤32GB)THP 禁用 + 显式大页2MB否(COW 避免)
PostgreSQL显式大页(huge_pages=on)2MB是(shared_buffers)
KVM 虚拟机显式大页(memory-backend-file)2MB 或 1GB可选
DPDK 数据面显式大页(hugetlbfs)2MB 或 1GB是(PMD 共享)
通用服务器THP=madvise(保守启用)2MB按需
HPC 科学计算显式大页 + NUMA 绑定1GB否(性能优先)

8.2 调优 Checklist

□ 确定是否真的需要大页(TLB Miss > 5% 时间)
□ 选择合适的大页尺寸(2MB 通常最优,1GB 仅特大内存场景)
□ 数据库场景禁用 THP,改用显式大页
□ NUMA 环境下确保大页数与 CPU 核心数对齐
□ 监控 HugePages_Free 判断大页是否充足
□ 非大页内存需求不要超过总 RAM 的 50%(为应用留空间)
□ 设置 vm.nr_overcommit_hugepages 应对临时峰值
□ 数据库大页场景禁用 swap(swap 时大页无法拆分)
□ 评估启动参数预留 vs 运行时分配(预留更可靠)
□ 配合 mlock 防止大页被换出

8.3 关键参数速查表

# /proc/sys/vm/ 目录
vm.nr_hugepages = 1024              # 系统大页总数
vm.nr_overcommit_hugepages = 0      # 超额分配大页数
vm.hugetlb_shm_group = 0            # 可访问大页的组 ID
vm.nr_hugepages_mempolicy = 0       # NUMA 策略大页
vm.hugepages_treat_as_movable = 0   # 大页可移动(用于内存热插拔)

# THP 配置
/sys/kernel/mm/transparent_hugepage/enabled = madvise
/sys/kernel/mm/transparent_hugepage/defrag = defer+madvise
/sys/kernel/mm/transparent_hugepage/khugepaged/scan_sleep_millisecs = 10000

8.4 性能测试基准参考

# 一键测试脚本(sysbench + perf)
#!/bin/bash

echo "=== 标准页基准 ==="
echo always > /sys/kernel/mm/transparent_hugepage/enabled
sysbench memory --memory-block-size=1M --memory-total-size=10G run
perf stat -e dtlb_load_misses.miss_causes_a_walk \
  sysbench memory --memory-block-size=1M --memory-total-size=1G run 2>&1 | tail -3

echo "=== 大页基准 ==="
echo 512 > /proc/sys/vm/nr_hugepages
echo never > /sys/kernel/mm/transparent_hugepage/enabled
hugeadm --pool-pages-min=2MB:256
sysbench memory --memory-block-size=1M --memory-total-size=10G run
perf stat -e dtlb_load_misses.miss_causes_a_walk \
  sysbench memory --memory-block-size=1M --memory-total-size=1G run 2>&1 | tail -3

九、大页机制的未来演进

9.1 Linux 6.x 内核的大页改进

Linux 内核社区持续在大页方面推进改进:

  • Multi-size THP (mTHP):Linux 6.3+ 引入,允许 THP 使用介于 4KB 和 2MB 之间的任意对齐大小(如 64KB、128KB)。ARM64 架构下尤其有用,可利用其支持的连续页表条目(Contiguous PTE)。
  • Large folio for page cache:Linux 6.6+ 开始为 page cache 支持 folio(不一定是 PMD 尺寸的页,减少浪费)。
  • TPP(Transparent Page Placement):优化跨 NUMA 节点的大页迁移。
  • Huge page demotion:将不再使用的大页拆分回标准页,提升内存利用率。
  • CXL memory 的大页支持:为 CXL 连接扩展内存设计的大页优化策略。

9.2 eBPF 与大页优化

eBPF 可以被用于分析大页的使用效率,识别哪些进程 THP 合并在但有些浪费:

// eBPF 程序监控 khugepaged 合并效率
SEC("kprobe/khugepaged_alloc_page")
int trace_khugepaged_alloc(struct pt_regs *ctx) {
    u32 pid = bpf_get_current_pid_tgid() >> 32;
    u64 ts = bpf_ktime_get_ns();
    
    struct event e = {};
    e.pid = pid;
    e.timestamp = ts;
    e.gfp_mask = PT_REGS_PARM2(ctx);
    
    bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &e, sizeof(e));
    return 0;
}

// 使用 bpftrace 一键追踪
bpftrace -e 'kprobe:khugepaged_alloc_page { 
    @start[tid] = nsecs; 
} 
kretprobe:khugepaged_alloc_page /@start[tid]/ { 
    @latency_ms = (nsecs - @start[tid]) / 1000000; 
    delete(@start[tid]); 
}'

十、总结

Linux 内核的大页机制是高性能系统中最有效的优化手段之一,它通过增大页面尺寸来缓解 TLB Miss 带来的性能下降。关键要点回顾:

  • T LB Miss 是大页优化的核心动机:当工作集远超 TLB 覆盖范围时,大页可以带来数倍的性能提升
  • 选择合适的大页方式:数据库/虚拟化场景使用显式大页 + 禁用 THP;通用服务器使用 THP=madvise
  • NUMA 感知至关重要:大页跨越 NUMA 节点会严重削弱性能收益
  • 监控与验证:使用 perf stat 验证 TLB Miss 率是否降低,避免盲目调优
  • 注意副作用:大页不可被 swap、占用固定内存、碎片化时分配困难

在数据库、虚拟化、网络数据包处理等场景中,花 30 分钟配置合适的大页策略,通常能获得 15%~50% 的性能回报——这是系统调优中最具性价比的优化之一。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部