You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PCIe端点BAR映射异常:memcpy段错误与数据传输性能问询

问题

我将PCIe端点设备连接至主机,把它的512MB BAR做mmap后用memcpy传输数据,耗时约2.5s;但仅映射BAR的100字节却执行512MB memcpy时,0.5s内就触发了段错误。之前误以为段错误后BAR末端数据和完整映射时一致,实际并非如此。想问为什么会出现这种数据写入情况,且速度远快于正常方式?

完整映射BAR的代码(耗时2.5s)

fd = open(filename, O_RDWR | O_SYNC)

map_base = mmap(NULL, 536870912, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

int rand_fd = open(infile, O_RDONLY);
rand_base = mmap(0, 536870912, PROT_READ, MAP_SHARED, rand_fd, 0);
memcpy(map_base, rand_base, 536870912);

if(munmap(map_base, map_size) == -1)
{
    PRINT_ERROR;
}
close(fd);

仅映射100字节的代码(耗时0.5s)

fd = open(filename, O_RDWR | O_SYNC)

map_base = mmap(NULL, 100, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

int rand_fd = open(infile, O_RDONLY);
rand_base = mmap(0, 536870912, PROT_READ, MAP_SHARED, rand_fd, 0);
memcpy(map_base, rand_base, 536870912);

if(munmap(map_base, map_size) == -1)
{
    PRINT_ERROR;
}
close(fd);

补充说明:我使用pcimem工具校验写入数据。

分析与解答

1. 数据写入与段错误的本质

当仅映射BAR的100字节时,memcpy会从map_base开始尝试连续写入512MB数据,这完全超出了内核分配的虚拟内存映射范围:

  • 映射范围内的100字节会正常写入PCIe设备的BAR空间。
  • 超出映射范围的地址访问会触发内核页错误,由于这些虚拟地址未绑定到PCIe BAR的物理地址,内核无法完成映射,最终抛出SIGSEGV信号终止进程。
  • 之前误以为末端数据正确是误判,超出映射范围的写入根本没有成功提交到PCIe设备,页错误会直接中断写入流程,未完成的操作不会生效。

2. 速度差异的核心原因

两种场景的耗时差距,本质是实际完成的写入量不同:

  • 完整映射时,memcpy需要把512MB数据全部通过PCIe总线写入设备,受限于PCIe链路的实际有效带宽(比如x1链路有效带宽通常低于8Gbps),再加上O_SYNC标志强制每笔写入同步到设备,所以耗时长达2.5s。
  • 部分映射时,memcpy在触发段错误前仅完成了少量数据写入(通常是几个内存页的大小,远小于512MB),内核触发页错误并终止进程的速度很快,因此总耗时仅0.5s左右。

内容的提问来源于stack exchange,提问作者userYou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 12:18:26