Linux内核PCIe软件框架深度解析:从RC到EP的驱动模型与核心数据结构

news2026/3/20 11:44:02
1. 从零开始理解Linux内核PCIe软件框架的“世界观”如果你刚接触Linux内核里的PCIe驱动开发可能会被一堆缩写和数据结构搞得晕头转向。RC、EP、pci_host_bridge、pci_epc……这些名词听起来就让人头大。别急我刚开始搞这块的时候也这样感觉像在看天书。但后来我明白了内核开发者们设计这套框架其实和我们日常生活中的快递物流系统非常像。今天我就用这个比喻带你轻松走进Linux PCIe软件框架的世界。你可以把整个PCIe系统想象成一个庞大的快递网络。Root Complex也就是RC就是这个网络的总调度中心。它坐镇在CPU旁边负责管理所有进出CPU的“货物”也就是数据。而Endpoint也就是EP就是网络末端的各个收发站点比如你的显卡、网卡、NVMe硬盘它们负责生产或消费这些“货物”。Linux内核的PCIe软件框架就是为管理这个庞大、高效的物流系统而设计的一套“管理软件”和“操作手册”。这套框架的核心目标就两个一是让CPU总调度中心能发现、识别并管理所有挂上来的设备收发站点二是让这些设备能正常工作和CPU顺畅地通信。为了实现这个目标内核采用了经典的分层设计思想把复杂的问题拆解成一个个相对独立的模块。对于RC模式框架主要分五层对于EP模式则分六层。每一层各司其职下层为上层提供服务上层调用下层的接口。这种设计的好处是写驱动的人只需要关心自己负责的那一层比如你如果是做RC控制器芯片驱动的就主要和硬件寄存器打交道如果你是做NVMe硬盘驱动的就主要关注块设备读写命令不用去操心PCIe链路是怎么建立的。理解这个框架对于内核开发者和嵌入式工程师来说至关重要。当你的板子上的PCIe设备识别不出来或者性能不达标时你就能像侦探一样沿着这套框架的脉络从应用层一路追踪到硬件寄存器快速定位问题到底出在设备驱动、核心层还是最底层的控制器驱动。接下来我们就深入这个“物流中心”和“收发站点”的内部看看它们具体是怎么运作的。2. 深入“物流中心”RC模式软件框架全解析RC模式即Root Complex模式是Linux内核作为PCIe总线“主机端”的运行模式。这就像快递公司的总部它要管理所有的运输车辆总线、仓库内存地址空间和派送规则。整个RC软件框架自底向上分为五层每一层都有明确的分工。2.1 基石RC控制器驱动层这是最底层直接和硬件对话的一层。不同的SoC厂商比如Rockchip瑞芯微、NXP、TI他们的PCIe控制器硬件设计都不一样。因此内核需要为每一款控制器编写一个特定的驱动程序这就是RC Controller Driver。它的工作非常“接地气”初始化控制器硬件、配置PCIe链路的速度和宽度比如是Gen3 x4还是Gen4 x8、设置内存映射窗口告诉CPU设备的BAR空间映射到系统内存的哪个位置、处理控制器产生的中断等等。你可以把它看作是快递公司里专门负责保养和驾驶特定型号卡车的司机团队。以原始文章中提到的RK3588平台为例它的驱动就是一个标准的Linux平台驱动platform_driverstatic struct platform_driver rk_plat_pcie_driver { .driver { .name rk-pcie, .of_match_table rk_pcie_of_match, // 匹配设备树中的节点 .pm rockchip_dw_pcie_pm_ops, // 电源管理操作 }, .probe rk_pcie_probe, // 探测函数驱动入口 }; module_platform_driver(rk_plat_pcie_driver);在rk_pcie_probe函数里驱动会读取设备树Device Tree的配置申请内存资源初始化DesignWare PCIe IP核RK3588使用的通用IP最后向内核的核心层注册自己。这一层驱动是芯片相关的如果你要移植内核到一个新平台这部分通常是工作量最大的地方之一。我踩过的坑是有时候硬件时序没调好probe函数能过但设备就是枚举不出来这时候就得拿着示波器和芯片手册一点点对波形了。2.2 核心枢纽PCIe Core层这一层是框架的大脑和骨架它把底层五花八门的控制器驱动抽象化提供了一个统一的模型来管理所有PCIe总线和设备。无论下面是RK3588还是其他芯片上层看到的接口都是一样的。它主要定义了四个核心数据结构理解了它们就理解了PCIe Core的灵魂。2.2.1 总指挥pci_host_bridgestruct pci_host_bridge代表一个PCIe主机桥它是整个PCIe域Domain的根。你可以把它想象成快递总部的调度指挥部。struct pci_host_bridge { struct device dev; // 内嵌的设备结构 struct pci_bus *bus; // 指向它管理的根总线bus 0 struct pci_ops *ops; // 访问配置空间的方法关键 struct list_head windows; // 地址映射窗口链表CPU物理地址 - PCI总线地址 struct list_head dma_ranges; // DMA地址范围链表 // ... 其他成员 };其中ops指针至关重要它指向一个pci_ops结构体里面包含了read和write等函数。RC控制器驱动必须实现这些函数因为Core层和上层驱动正是通过这组函数来读写任何PCIe设备的配置空间的。这就好比调度指挥部必须有一套标准的无线电协议才能指挥所有车辆。windows链表则定义了系统内存地址和PCIe总线地址之间的转换关系是DMA能够正常工作的基础。内核提供了pci_alloc_host_bridge来创建这个结构并在pci_host_probe函数中以这个host_bridge为起点开始扫描枚举下游所有的PCIe设备和总线。2.2.2 交通干线pci_busstruct pci_bus代表一条PCIe总线。一个复杂的系统可能有多条总线它们通过PCIe桥Switch连接形成一棵树。这个结构体就是用来描述这条“公路”本身的。struct pci_bus { struct pci_bus *parent; // 父总线 struct list_head children; // 子总线链表 struct list_head devices; // 挂在这条总线上的设备链表 struct resource busn_res; // 这条总线管理的总线号范围 unsigned char number; // 总线编号 unsigned char max_bus_speed; // 支持的最大速度如PCI_SPEED_5_0GT/s // ... 其他成员 };内核在枚举过程中会动态创建和链接这些pci_bus结构。从host_bridge的bus通常是bus 0开始每发现一个桥设备Switch或PCIe-PCI桥就创建一个新的pci_bus作为子总线并分配一个总线号。通过pci_find_bus函数可以根据域和总线号快速找到对应的pci_bus对象。管理好这棵“总线树”是系统能够正确寻址每个设备的前提。2.2.3 运输车辆pci_devstruct pci_dev描述一个具体的PCIe设备它是内核中设备驱动的操作对象。无论是显卡、网卡还是PCIe桥本身在驱动眼里都是一个pci_dev。struct pci_dev { struct list_head bus_list; // 在所属总线设备链表中的节点 struct pci_bus *bus; // 所属总线 unsigned int devfn; // 设备号和功能号的编码 unsigned short vendor; // 厂商ID unsigned short device; // 设备ID struct pci_driver *driver; // 绑定到这个设备的驱动 struct resource resource[DEVICE_COUNT_RESOURCE]; // 设备的资源BAR空间 // ... 大量其他成员包含配置空间信息、状态等 };当Core层枚举到一个设备时它会调用pci_alloc_dev分配一个pci_dev结构并从设备的配置空间头中读取vendor ID、device ID、BAR等信息填充到该结构中。resource数组尤其重要它保存了设备声明的每个BARBase Address Register的大小和类型内存空间或I/O空间。驱动在probe时通常会调用pci_request_regions来申请这些资源并将其映射到内核虚拟地址空间从而才能对设备的寄存器进行读写操作。2.2.4 驾驶员手册pci_driverstruct pci_driver描述一个PCIe设备驱动。它定义了驱动如何与设备“打交道”。struct pci_driver { const char *name; const struct pci_device_id *id_table; // 驱动支持的设备ID表 int (*probe)(struct pci_dev *dev, const struct pci_device_id *id); // 设备发现时的入口 void (*remove)(struct pci_dev *dev); // 设备移除时的清理 int (*suspend)(struct pci_dev *dev, pm_message_t state); // 电源管理-挂起 int (*resume)(struct pci_dev *dev); // 电源管理-恢复 // ... 其他操作 };驱动通过pci_register_driver向内核注册自己。注册时内核会将驱动的id_table与系统中所有pci_dev的vendor/device ID进行比对。一旦匹配成功就会调用驱动的probe函数。在probe函数里驱动完成设备的初始化、资源申请、中断注册等一系列操作让设备就绪。这个“匹配-探测”的机制是Linux设备驱动模型的精髓保证了驱动的可移植性和模块化。2.3 设备驱动层与用户空间在Core层之上就是各种各样的PCIe设备驱动比如前面提到的pcieportPCIe端口/桥驱动和nvmeNVMe硬盘驱动。它们基于Core层提供的稳定接口pci_devpci_read_config_dword等开发无需关心底层硬件差异。再往上设备驱动会根据设备类型向内核的其他子系统注册自己。例如NVMe驱动会向块设备层注册一个gendisk网卡驱动会向网络栈注册一个net_device。最终在虚拟文件系统层如/dev目录下创建出用户空间可以访问的设备节点如/dev/nvme0n1应用程序通过标准的系统调用read,write,ioctl就能使用这些硬件了。3. 透视“收发站点”EP模式软件框架详解EP模式即Endpoint模式是Linux内核作为PCIe“设备端”的运行模式。这就像快递网络中的一个加盟站点它需要遵循总部RC制定的规则上报自己的货物处理能力BAR空间、中断并等待总部的指令。EP框架比RC多了一层共六层因为它多了一个在用户空间进行灵活配置的机制。3.1 底层对接EP控制器驱动层和RC类似最底层是EP Controller Driver它与具体的EP控制器硬件交互。例如Rockchip RK3399的EP驱动static struct platform_driver rockchip_pcie_ep_driver { .driver { .name rockchip-pcie-ep, .of_match_table rockchip_pcie_ep_of_match, }, .probe rockchip_pcie_ep_probe, };它的核心任务是在probe函数中初始化EP控制器硬件并创建一个pci_epc对象后面会讲注册到核心层。这个驱动实现了硬件相关的细节比如如何设置设备类型Endpoint、如何配置Outbound地址转换ATU等。3.2 抽象核心EP控制器核心层这是EP框架的抽象层核心数据结构是struct pci_epc它代表一个Endpoint控制器。struct pci_epc { struct device dev; struct list_head pci_epf; // 挂载在此控制器上的EP Function链表 const struct pci_epc_ops *ops; // 控制器操作函数集灵魂所在 struct pci_epc_mem **windows; // Outbound地址窗口 u8 max_functions; // 支持的最大Function数量 // ... 其他成员 };pci_epc_ops是这个结构体的灵魂它定义了一组回调函数write_header,set_bar,raise_irq等。EP控制器驱动必须实现这组函数。而上层的EP Function驱动则通过Core层提供的封装函数如pci_epc_set_bar来调用这些ops从而间接操作硬件。这完美体现了分层设计Function驱动不知道下面具体是RK3399还是其他芯片它只调用标准APIEPC驱动则负责将这些标准API翻译成自己硬件的寄存器操作。3.3 功能单元EP Function核心层一个EP控制器EPC上可以虚拟出多个功能Function每个功能对应一个struct pci_epf设备。这就像一台多功能一体机EPC可以充当打印机Function 1、扫描仪Function 2等。struct pci_epf { const char *name; struct pci_epf_header *header; // EPF的配置空间头信息 struct pci_epf_bar bar[6]; // EPF申请的BAR资源 u8 msi_interrupts; // 需要的MSI中断数量 u8 func_no; // 功能号 struct pci_epc *epc; // 所属的EP控制器 struct pci_epf_driver *driver; // 绑定的驱动 };同时每个EP Function也需要自己的驱动即struct pci_epf_driver。它也有id_table、probe、remove以及一个特殊的ops里面包含bind和unbind函数。当EPF设备与EPC控制器成功绑定后bind函数会被调用在这里EPF驱动可以通过前面提到的pci_epc_set_bar等API向EPC申请资源、配置自己的类型和功能。3.4 灵活配置EP Configfs与用户空间交互这是EP模式颇具特色的一层。它通过Linux的configfs文件系统通常挂载在/sys/kernel/config在用户空间暴露出一套文件接口。开发者或用户可以在/sys/kernel/config/pci_ep/目录下通过创建目录、写入文件等简单的文件操作来动态创建EPF设备、将其绑定到某个EPC控制器、并配置其BAR大小、中断类型等属性。这意味着你可以不重新编译内核或加载驱动模块就改变EP设备的行为。这对于调试和功能验证来说极其方便。比如你可以快速创建一个测试用的EP Function配置它使用MSI-X中断和1MB的内存BAR然后让主机端来扫描测试。3.5 功能实现EP Function驱动示例内核中有一个非常经典的示例驱动pci-epf-test。它实现了一个用于测试的EP Function。当它通过configfs绑定到EPC后主机端会看到一个标准的PCIe设备。主机可以向这个设备的特定BAR地址写入测试数据EP端的pci-epf-test驱动会读取这些数据进行校验再写回另一段数据从而完成一个简单的回环测试。这个驱动是学习EP驱动开发的最佳范例通过阅读它的bind、unbind以及中断处理函数你能清晰地看到一个EPF驱动的生命周期和如何与EPC核心层交互。4. 实战指南调试与开发中的关键技巧理解了框架最终还是要落到开发和调试上。根据我多年的经验无论是调试RC还是EP思路和工具都至关重要。4.1 RC端问题排查设备枚举失败这是最常见的问题。当你发现lspci命令看不到设备时可以按以下层次排查硬件与链路层首先确认板子供电、时钟、复位信号是否正常。使用示波器或逻辑分析仪测量PCIe的参考时钟和差分信号线。确保RC和EP的链路训练能成功通常可以通过读取控制器的状态寄存器来确认链路是否处于“L0”状态。控制器驱动层检查RC控制器驱动的probe函数是否成功执行。在驱动代码中添加printk确认pci_host_probe是否被调用。重点检查pci_ops中的read/write函数是否正确实现因为枚举过程就是通过反复调用这两个函数来扫描总线的。一个常见的错误是地址映射不对导致读写配置空间时发生数据中止Data Abort。Core层枚举如果控制器驱动正常但设备还是没出现可以打开内核的PCI调试信息CONFIG_PCI_DEBUG观察枚举过程的日志。这能告诉你扫描到了哪个总线号在哪个设备号上卡住了。设备与驱动匹配设备出现在lspci中但没有被驱动绑定。检查dmesg日志看是否输出了“no driver found”。这通常是驱动的id_table没有包含你设备的vendor/device ID或者驱动模块没有加载。使用modprobe加载对应驱动或者检查驱动代码的ID表。4.2 EP端开发要点资源申请与中断处理编写一个EP Function驱动你需要重点关注两个部分资源申请BAR设置在EPF驱动的bind函数中你需要初始化pci_epf_bar结构数组描述每个BAR的类型32位/64位、可预取内存等和大小。然后调用pci_epc_set_bar。这里的关键是你申请的大小必须是2的幂并且对齐到自身大小。例如申请1MB的BAR大小就是0x100000。// 在bind函数中的示例片段 epf-bar[0].barno 0; epf-bar[0].size SZ_1M; // 1 MB epf-bar[0].flags PCI_BASE_ADDRESS_MEM_TYPE_32 | PCI_BASE_ADDRESS_MEM_PREFETCH; ret pci_epc_set_bar(epc, func_no, epf-bar[0]); if (ret) dev_err(dev, Failed to set BAR0\n);中断配置EP模式通常使用MSI或MSI-X中断。你需要告诉EPC你需要多少个中断向量。// 申请MSI-X中断 epf-msix_interrupts 4; // 需要4个MSI-X向量 ret pci_epc_set_msix(epc, func_no, epf-msix_interrupts, BAR_0, 0x0 /* offset */);当中断事件发生时在EPF驱动中调用pci_epc_raise_irq来触发一个中断。主机端的RC收到这个中断消息后会进行相应的处理。4.3 利用现有工具lspci与debugfs不要重复造轮子善用现有工具lspci -vvv这是你最好的朋友。它能列出所有PCIe设备的详细信息包括配置空间的所有内容、BAR地址、中断线IRQ、链路速度与宽度LnkSta、设备能力列表Capabilities等。在调试初期先用它确认设备是否被正确识别和配置。/sys/bus/pci/devices/sysfs提供了丰富的接口。你可以进入某个设备的目录如0000:01:00.0查看resource文件了解BAR映射查看config文件直接读取原始配置空间。/sys/kernel/debug/pci/如果内核启用了PCI调试CONFIG_PCI_DEBUG这个目录下会有更多底层信息比如总线树状图对于理解复杂的PCIe拓扑非常有帮助。内核的PCIe框架虽然庞大但结构清晰。掌握从RC到EP的分层模型理解pci_host_bridge、pci_dev、pci_epc、pci_epf这几个核心数据结构之间的关系就像拿到了这个复杂物流系统的地图。无论是解决一个诡异的枚举问题还是为一块新的硬件编写驱动你都能知道该从哪里入手该查看哪一层的代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2410250.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…