news 2026/10/20 4:24:42

FC卡驱动源码编译实战:从环境准备到ko加载全流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FC卡驱动源码编译实战:从环境准备到ko加载全流程

1. 从零搞懂FC卡驱动源码编译:为什么这件事值得认真对待

做存储和服务器运维的朋友,对FC卡(Fibre Channel Host Bus Adapter,光纤通道主机总线适配器)肯定不陌生。这东西在SAN存储网络里就是服务器和存储阵列之间的“高速公路收费站”,负责把主机的IO请求打包成FC帧发出去。市面上常见的FC卡品牌就那么几家,QLogic、Emulex、Broadcom(收购了Emulex之后)以及Marvell(收购了QLogic之后),每一家的驱动源码结构和编译方式都有差异。

很多人拿到FC卡驱动源码之后第一反应是懵的——一堆C文件、Makefile、Kconfig、还有各种脚本,不知道从哪下手。网上搜到的教程要么太老,要么只讲了个大概,真正动手编译的时候各种报错。我自己前前后后编译过不下十次不同版本的FC卡驱动,踩过的坑包括内核版本不匹配、头文件路径找不到、编译出来的ko文件加载失败、固件版本对不上等等。这篇文章就是把这些经验整理出来,给需要自己编译FC卡驱动的朋友一个可以直接参考的流程。

FC卡驱动源码编译这件事,说白了就是把厂商提供的驱动源代码,在你的目标系统上编译成内核模块(.ko文件),然后加载到内核里,让操作系统能识别并正常使用这块FC卡。听起来简单,但实际操作中涉及内核头文件、编译工具链、内核版本匹配、固件加载等多个环节,任何一个环节出问题都会导致编译失败或者驱动加载异常。

这篇文章适合谁看?如果你是系统运维工程师,需要给特定内核版本的服务器编译FC卡驱动;如果你是存储工程师,需要调试FC卡驱动的问题;或者你只是对Linux内核模块编译感兴趣,想拿FC卡驱动练手——都可以参考这个流程。我尽量把每一步的原理和操作都讲清楚,让不同基础的人都能跟着做下来。

2. 编译前的准备工作:环境、工具链和源码获取

2.1 确认目标系统的内核版本和架构

编译内核模块的第一原则是:编译时使用的内核头文件版本必须和运行时的内核版本完全一致。这不是“差不多就行”的事情,是“差一个字符都不行”。因为内核模块在加载时会校验版本魔术字(vermagic),包括内核版本号、SMP标志、抢占模式、模块版本等。任何一个不匹配,加载时就会报“invalid module format”错误。

所以第一步,先确认目标系统的内核版本:

uname -r

输出类似4.19.90-2109.1.0.0100.oe1.x86_64这样的字符串。记下这个完整版本号,后面编译时要用。

然后确认系统架构:

uname -m

FC卡驱动在x86_64和aarch64上都有,确认架构是为了选对源码包和编译参数。

2.2 安装内核头文件和编译工具链

确认内核版本之后,需要安装对应的内核开发包。不同发行版的包名不一样:

发行版内核头文件包名编译工具包名
RHEL/CentOSkernel-devel-$(uname -r)gcc, make, elfutils-libelf-devel
Ubuntu/Debianlinux-headers-$(uname -r)build-essential, libelf-dev
openEulerkernel-devel-$(uname -r)gcc, make, elfutils-libelf-devel
SUSEkernel-default-develgcc, make, elfutils-libelf-devel

安装命令以RHEL系为例:

yum install -y kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc make elfutils-libelf-devel

这里有个坑要注意:有些系统默认安装的kernel-devel版本可能和当前运行的内核版本不一致,比如系统更新过内核但没重启,uname -r显示的是旧内核,而/usr/src/kernels/目录下只有新内核的头文件。这种情况下要么重启到新内核,要么手动安装对应旧版本的头文件包。

安装完成后,检查/lib/modules/$(uname -r)/build这个符号链接是否指向正确的内核源码目录:

ls -l /lib/modules/$(uname -r)/build

正常应该指向/usr/src/kernels/$(uname -r)。如果这个链接不存在或者指向错误,编译时就会找不到内核头文件。

2.3 获取FC卡驱动源码

FC卡驱动源码的获取渠道主要有几个:厂商官网下载、发行版自带源码包、厂商提供的DKMS包。以QLogic和Emulex为例,厂商通常会提供一个tar包,里面包含驱动源码、Makefile、README和固件文件。

拿到源码包之后,先解压看看目录结构:

tar xzf qla2xxx-src-v10.02.00.100.tar.gz cd qla2xxx-src-v10.02.00.100 ls -la

典型的FC卡驱动源码目录结构是这样的:

qla2xxx-src-v10.02.00.100/ ├── Makefile ├── README ├── qla_attr.c ├── qla_bsg.c ├── qla_dbg.c ├── qla_def.h ├── qla_devtbl.h ├── qla_dfs.c ├── qla_fw.c ├── qla_gs.c ├── qla_init.c ├── qla_iocb.c ├── qla_isr.c ├── qla_mbx.c ├── qla_mr.c ├── qla_nvme.c ├── qla_os.c ├── qla_settings.h ├── qla_sup.c ├── qla_target.c ├── qla_version.h └── ...

不同厂商的驱动文件名前缀不同,QLogic的是qla2xxx,Emulex的是lpfc,但结构大同小异。核心文件包括:*_os.c(操作系统接口层)、*_init.c(初始化)、*_isr.c(中断处理)、*_mbx.c(邮箱命令)、*_iocb.c(IO控制块)等。

提示:下载源码时一定要确认驱动版本和FC卡型号、固件版本的兼容性。厂商的README文件里通常会有一个兼容性矩阵表,花五分钟看一下能省掉后面几个小时的排查时间。

3. 核心编译流程拆解:从Makefile到ko文件

3.1 读懂驱动源码的Makefile结构

FC卡驱动的Makefile通常有两种形式:一种是独立编译的Makefile,直接调用内核的编译框架;另一种是集成到内核源码树里的Kbuild文件。厂商提供的独立源码包一般是前者。

一个典型的FC卡驱动Makefile长这样:

# 指定内核源码路径 KERNELDIR ?= /lib/modules/$(shell uname -r)/build # 指定当前目录 PWD := $(shell pwd) # 目标模块名 obj-m := qla2xxx.o # 模块包含的目标文件 qla2xxx-objs := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o \ qla_gs.o qla_dbg.o qla_sup.o qla_attr.o qla_bsg.o \ qla_dfs.o qla_gs.o qla_nvme.o qla_target.o qla_fw.o # 默认目标 default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules # 清理 clean: $(MAKE) -C $(KERNELDIR) M=$(PWD) clean # 安装 install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

这个Makefile的核心逻辑是:通过obj-m告诉内核编译框架要生成一个名为qla2xxx.ko的模块,通过qla2xxx-objs列出组成这个模块的所有目标文件。然后调用make -C $(KERNELDIR) M=$(PWD) modules,让内核的编译系统在当前目录下执行模块编译。

这里的关键点是KERNELDIR变量。它指向内核源码目录,编译时会去这个目录下找内核的配置、头文件和编译规则。如果这个路径不对,编译直接失败。

3.2 编译参数的配置与调整

在正式编译之前,通常需要根据目标环境调整一些编译参数。这些参数一般在Makefile或者单独的配置文件中定义。

常见的需要关注的参数包括:

  • CONFIG_DEBUG_INFO:是否生成调试信息。调试阶段建议开启,生产环境建议关闭以减小模块体积。
  • CONFIG_FC_DEBUG:FC协议层的调试开关。开启后会输出大量调试日志,排查问题时有用,但会影响性能。
  • CONFIG_SCSI_QLA_FC:QLogic FC驱动的配置选项,决定是否编译特定功能模块。
  • CONFIG_NVME_FC:是否支持NVMe over FC。如果不需要NVMe over FC功能,可以关闭以减小模块体积。

这些参数通常通过内核的.config文件或者编译时的命令行参数传递。如果驱动源码包里有Makefile中定义的EXTRA_CFLAGS,可以直接在里面添加:

EXTRA_CFLAGS += -DCONFIG_FC_DEBUG=1

或者通过命令行传递:

make -C /lib/modules/$(uname -r)/build M=$(pwd) EXTRA_CFLAGS="-DCONFIG_FC_DEBUG=1" modules

注意:不要随意修改驱动源码中的核心逻辑代码。如果只是为了编译通过而修改代码,很可能会引入难以排查的运行时问题。编译参数能解决的问题,不要动代码。

3.3 执行编译并解读编译输出

准备工作做完之后,就可以执行编译了。在驱动源码目录下直接运行:

make

或者指定内核路径:

make KERNELDIR=/lib/modules/$(uname -r)/build

编译过程会输出大量信息,包括每个源文件的编译命令、警告和错误。正常编译的输出大概是这样:

make -C /lib/modules/4.19.90-2109.1.0.0100.oe1.x86_64/build M=/root/qla2xxx-src-v10.02.00.100 modules make[1]: Entering directory '/usr/src/kernels/4.19.90-2109.1.0.0100.oe1.x86_64' CC [M] /root/qla2xxx-src-v10.02.00.100/qla_os.o CC [M] /root/qla2xxx-src-v10.02.00.100/qla_init.o CC [M] /root/qla2xxx-src-v10.02.00.100/qla_mbx.o ... LD [M] /root/qla2xxx-src-v10.02.00.100/qla2xxx.o Building modules, stage 2. MODPOST 1 modules CC /root/qla2xxx-src-v10.02.00.100/qla2xxx.mod.o LD [M] /root/qla2xxx-src-v10.02.00.100/qla2xxx.ko make[1]: Leaving directory '/usr/src/kernels/4.19.90-2109.1.0.0100.oe1.x86_64'

看到最后生成了qla2xxx.ko文件,就说明编译成功了。用ls -lh确认一下文件大小和生成时间:

ls -lh qla2xxx.ko

编译过程中常见的警告包括未使用的变量、类型转换警告等,这些一般不影响功能。但如果出现error级别的信息,就必须解决才能继续。

4. 编译后的验证与加载:确保驱动真正能用

4.1 检查ko文件的版本信息和依赖关系

编译出来的ko文件不能直接拿来就用,先要检查它的版本信息是否和目标内核匹配:

modinfo qla2xxx.ko

输出会显示模块的详细信息,包括filename、version、license、description、author、srcversion、depends、vermagic等。重点看vermagic这一行:

vermagic: 4.19.90-2109.1.0.0100.oe1.x86_64 SMP mod_unload modversions

这个字符串必须和uname -r的输出以及目标内核的vermagic完全一致。如果编译时用的内核头文件版本和运行时内核版本不一致,这里就会显示不同的版本号,加载时必然失败。

还要看depends字段,确认模块依赖的其他模块是否已经加载。FC卡驱动通常依赖scsi_mod、scsi_transport_fc、libfc等模块。可以用lsmod检查这些依赖模块的状态。

4.2 加载驱动模块并验证FC卡识别

确认版本信息无误后,就可以加载模块了:

insmod qla2xxx.ko

或者用modprobe(需要先把ko文件放到/lib/modules/$(uname -r)/extra/目录下并执行depmod):

cp qla2xxx.ko /lib/modules/$(uname -r)/extra/ depmod -a modprobe qla2xxx

加载成功后,用dmesg查看内核日志,应该能看到类似这样的输出:

[ 1234.567890] QLogic Fibre Channel HBA Driver: 10.02.00.100 [ 1234.567891] qla2xxx [0000:3b:00.0]-001d: : Found an ISP2722 irq 150 iobase 0xffffc9000a400000. [ 1234.567892] scsi host6: qla2xxx [ 1234.567893] qla2xxx [0000:3b:00.0]-00fb:6: QLogic ISP2722 PCIe (0x00000000, 0x00000000) @ 0000:3b:00.0. [ 1234.567894] qla2xxx [0000:3b:00.0]-00fd:6: Firmware version 8.07.00 (90d5).

然后用lspci确认FC卡被识别:

lspci | grep -i fibre

应该能看到类似Fibre Channel: QLogic Corp. ISP2722-based 16Gb Fibre Channel to PCIe Adapter的输出。

再用lsblk或者fdisk -l确认FC卡上连接的存储设备是否被识别为块设备。如果一切正常,说明驱动编译和加载都成功了。

4.3 固件加载的注意事项

FC卡驱动通常需要加载固件才能正常工作。固件文件一般以.bin结尾,放在/lib/firmware/目录下。驱动加载时会自动请求固件,如果固件文件不存在或者版本不匹配,dmesg里会报错:

qla2xxx [0000:3b:00.0]-00af:6: Failed to load firmware image (qla2xxx_fw.bin).

解决方法是把厂商提供的固件文件复制到/lib/firmware/目录下,然后重新加载驱动:

cp qla2xxx_fw.bin /lib/firmware/ rmmod qla2xxx insmod qla2xxx.ko

提示:固件版本和驱动版本之间有兼容性要求。厂商的README里通常会说明哪个驱动版本对应哪个固件版本。不要混用不同版本的驱动和固件,否则可能出现FC链路不稳定、IO超时等问题。

5. 常见编译错误与排查方法实录

5.1 内核头文件缺失或版本不匹配

这是最常见的编译错误,报错信息通常是:

make[1]: *** /lib/modules/4.19.90-2109.1.0.0100.oe1.x86_64/build: No such file or directory. Stop.

或者:

fatal error: linux/module.h: No such file or directory

原因很明确:内核头文件没有安装,或者/lib/modules/$(uname -r)/build符号链接指向的目录不存在。解决方法就是安装对应版本的内核开发包,或者手动创建符号链接:

ln -s /usr/src/kernels/4.19.90-2109.1.0.0100.oe1.x86_64 /lib/modules/$(uname -r)/build

5.2 编译过程中出现函数未定义错误

报错信息类似:

ERROR: "fc_attach_transport" [qla2xxx.ko] undefined!

这说明驱动依赖的某个内核符号在当前内核中没有导出。可能的原因有两个:一是内核配置中没有开启对应的功能模块(比如CONFIG_SCSI_FC_ATTRS没有开启);二是内核版本太新或太旧,符号名称发生了变化。

排查方法是先确认内核配置:

grep CONFIG_SCSI_FC_ATTRS /boot/config-$(uname -r)

如果输出是# CONFIG_SCSI_FC_ATTRS is not set,说明内核没有编译FC传输层支持,需要重新编译内核或者换一个开启了该选项的内核。

5.3 模块加载时报invalid module format

这个错误的完整信息是:

insmod: ERROR: could not insert module qla2xxx.ko: Invalid module format

原因就是前面提到的vermagic不匹配。用modinfo检查ko文件的vermagic,和uname -r对比,如果不一致,说明编译时用的内核头文件版本和当前运行的内核版本不同。解决办法是安装正确版本的内核头文件,重新编译。

还有一种可能是编译时开启了CONFIG_MODVERSIONS,但目标内核没有开启,或者反过来。这种情况下需要调整编译参数,确保和内核配置一致。

5.4 FC卡识别不到或链路异常

驱动加载成功,lspci也能看到FC卡,但dmesg里报链路初始化失败:

qla2xxx [0000:3b:00.0]-00af:6: Failed to initialize adapter.

或者FC链路状态一直是Link Down:

cat /sys/class/fc_host/host6/port_state

输出Linkdown。

这种情况通常和固件、光模块、光纤线缆有关。排查步骤:

  1. 确认固件版本是否正确加载:dmesg | grep -i firmware
  2. 确认光模块是否被识别:cat /sys/class/fc_host/host6/port_name,如果没有输出或者输出异常,可能是光模块问题
  3. 检查光纤线缆连接:换一根线试试
  4. 检查交换机端口配置:确认交换机端口速率和FC卡速率匹配

5.5 常见问题速查表

问题现象可能原因排查方法解决方案
编译时报找不到内核头文件内核开发包未安装ls /lib/modules/$(uname -r)/build安装kernel-devel包
编译时报符号未定义内核配置未开启对应功能grep CONFIG_XXX /boot/config-$(uname -r)重新编译内核或换内核
加载时报invalid module formatvermagic不匹配modinfo xxx.ko | grep vermagic用正确版本头文件重新编译
加载时报unknown symbol依赖模块未加载lsmod | grep scsi先加载依赖模块
FC卡识别不到驱动未加载或PCI设备未识别lspci | grep -i fibre检查驱动加载和PCI插槽
链路状态Linkdown光模块/线缆/交换机问题cat /sys/class/fc_host/hostX/port_state检查物理连接和交换机配置
固件加载失败固件文件缺失或版本不对dmesg | grep -i firmware复制正确固件到/lib/firmware/

6. 实操心得与避坑经验

6.1 编译环境隔离的重要性

我强烈建议在编译FC卡驱动时使用独立的编译环境,不要在运行生产业务的主机上直接编译。原因有两个:一是编译过程会安装内核开发包、修改系统配置,可能影响生产环境;二是编译过程中如果出现内核头文件版本冲突,可能导致系统无法正常启动。

比较稳妥的做法是在一台同版本的测试机上编译,编译好ko文件之后再复制到生产机上加载。如果生产机和测试机的内核版本完全一致,编译出来的ko文件是可以通用的。

6.2 保留编译日志和版本记录

每次编译时,把编译日志保存下来:

make 2>&1 | tee build.log

同时记录以下信息:编译时间、内核版本、驱动版本、固件版本、编译参数。这些信息在后续排查问题时非常有用。我自己的习惯是在驱动源码目录下建一个build_info.txt文件,每次编译后更新:

Build Date: 2025-01-15 Kernel: 4.19.90-2109.1.0.0100.oe1.x86_64 Driver: qla2xxx v10.02.00.100 Firmware: 8.07.00 Flags: CONFIG_FC_DEBUG=0

6.3 不要忽略编译警告

虽然编译警告通常不影响功能,但有些警告可能暗示潜在的问题。比如“implicit declaration of function”警告,说明某个函数没有声明就被使用了,运行时可能出现不可预期的行为。再比如“incompatible pointer type”警告,可能导致64位系统上的指针截断问题。

我的做法是:对于新编译的驱动,先解决所有error,再尽量解决warning。如果某个warning确实无法解决(比如内核版本差异导致的),至少在build_info.txt里记录下来,后续出问题时可以回溯。

6.4 驱动版本回退的准备工作

升级FC卡驱动之前,一定要先备份当前正在使用的驱动版本。备份内容包括:当前加载的ko文件、固件文件、模块配置参数。这样如果新驱动有问题,可以快速回退。

回退步骤:

# 卸载新驱动 rmmod qla2xxx # 恢复旧驱动文件 cp /backup/qla2xxx.ko /lib/modules/$(uname -r)/extra/ depmod -a # 加载旧驱动 modprobe qla2xxx

注意:卸载FC卡驱动之前,确保该FC卡上没有正在进行的IO操作。如果FC卡上挂载了文件系统,先卸载文件系统再卸载驱动,否则可能导致IO hang或者数据丢失。

6.5 多路径环境的特殊考虑

如果服务器使用了多路径软件(比如DM-Multipath),编译和加载FC卡驱动时需要额外注意。新驱动加载后,FC卡的WWN可能会变化(虽然概率很低),导致多路径配置失效。加载驱动后,用multipath -ll检查多路径状态,确认所有路径都正常。

另外,如果服务器上有多块FC卡,编译驱动时要确认驱动支持所有卡的型号。有些驱动源码包只包含特定型号的支持,编译出来的驱动可能无法识别其他型号的FC卡。

7. 驱动源码编译的扩展思路

7.1 使用DKMS实现驱动自动重编译

每次内核更新后都手动重新编译FC卡驱动是一件很烦的事情。DKMS(Dynamic Kernel Module Support)可以解决这个问题。把驱动源码配置成DKMS模块后,每次内核更新时DKMS会自动重新编译驱动模块。

配置DKMS的基本步骤:

  1. 把驱动源码复制到/usr/src/qla2xxx-10.02.00.100/目录下
  2. 创建dkms.conf配置文件:
PACKAGE_NAME="qla2xxx" PACKAGE_VERSION="10.02.00.100" BUILT_MODULE_NAME[0]="qla2xxx" DEST_MODULE_LOCATION[0]="/extra" AUTOINSTALL="yes" MAKE[0]="make KERNELDIR=/lib/modules/${kernelver}/build" CLEAN="make clean"
  1. 执行dkms add -m qla2xxx -v 10.02.00.100和dkms build -m qla2xxx -v 10.02.00.100和dkms install -m qla2xxx -v 10.02.00.100

配置好之后,内核更新时DKMS会自动处理驱动重编译,省去手动操作的麻烦。

7.2 交叉编译FC卡驱动

在某些场景下,需要在x86机器上为aarch64架构的服务器编译FC卡驱动。这就是交叉编译。交叉编译的关键是使用正确的交叉编译工具链和对应架构的内核头文件。

基本命令:

make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- KERNELDIR=/path/to/arm64/kernel/build

交叉编译的难点在于工具链的配置和内核头文件的匹配。建议使用发行版提供的交叉编译工具链包,不要自己从源码编译工具链,否则很容易出现库依赖问题。

7.3 驱动源码的调试与日志分析

编译驱动时如果开启了调试选项,驱动运行时会输出大量调试日志。这些日志通过dmesg或者/var/log/messages查看。分析日志时重点关注以下几类信息:

  • qla2xxx [xxxx:xx:xx.x]-xxxx:x:格式的日志,前面的[xxxx:xx:xx.x]是PCI地址,后面的x是主机号
  • Failed to、Error、Timeout等关键字
  • 链路状态变化日志,比如Link Up、Link Down、Loop Up等

如果日志量太大,可以用dmesg -T | grep qla2xxx过滤,或者调整日志级别:

echo 4 > /sys/module/qla2xxx/parameters/ql2xextended_error_logging

这个参数的值越大,输出的日志越详细。排查问题时可以临时调大,问题解决后调回默认值。

7.4 驱动性能调优的编译参数

FC卡驱动的性能和一些编译参数有关。比如队列深度、中断合并、IO超时时间等。这些参数有些是在编译时确定的,有些是运行时通过模块参数调整的。

编译时可以关注的性能相关参数:

  • CONFIG_SCSI_QLA_FC_NVME:是否启用NVMe over FC支持,启用后会增加模块体积但支持NVMe协议
  • QLA2XXX_MAX_SNS_COMMAND_SIZE:SNS命令缓冲区大小,影响名称服务的查询效率
  • QLA2XXX_MAX_IO_SIZE:最大IO大小,影响大块数据传输的效率

运行时可以通过模块参数调整的:

modprobe qla2xxx ql2xmaxqdepth=64 ql2xloginretrycount=30

这些参数的调优需要根据实际业务场景和存储阵列的能力来确定,没有一套通用的最优值。建议在测试环境中逐步调整,观察性能变化。

8. 一些容易忽略的细节

编译FC卡驱动这件事,说难不难,说简单也不简单。核心就是三个匹配:内核版本匹配、驱动版本匹配、固件版本匹配。这三个匹配做好了,编译和加载基本不会出问题。

我在实际操作中体会最深的一点是:不要跳过README文件。厂商提供的README里包含了大量关键信息,包括兼容性矩阵、编译参数说明、已知问题列表。花十分钟读一遍README,能省掉后面几个小时的排查时间。

另外,编译环境的管理也很重要。建议维护一个专门的编译目录,里面保存不同版本的驱动源码、编译日志、build_info记录。这样需要回退或者对比时,能快速找到对应的版本。

最后分享一个小技巧:如果编译时遇到奇怪的错误,先执行make clean清理一下编译中间文件,再重新编译。有时候错误只是因为上次编译的残留文件导致的,清理后重新编译就能解决。这个技巧帮我解决过好几次莫名其妙的编译失败问题。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 4:23:52

PyTorch深度学习入门:从环境搭建到模型训练完整指南

1. 从零上手PyTorch:为什么它成了深度学习项目的第一选择如果你刚开始接触深度学习,或者从其他框架迁移过来,大概率会听到身边人反复提到PyTorch这个名字。它到底是什么?简单说,PyTorch是一个开源的深度学习框架&#…

作者头像 李华
网站建设 2026/10/20 4:23:48

AI重构低代码:轻流10.0的对话式搭建、智能流程与落地实践

低代码圈子里,这两年的关键词一直绕不开两个:一个是“AI原生”,一个是“业务自助”。但我看了几次发布会,总觉得产品演示和实际落地之间隔着一层纱——demo很炫,回到自家业务却不知道该从哪下手。这次轻流10.0的发布会…

作者头像 李华
网站建设 2026/10/20 4:23:14

Spring AI 1.0实战:基于Spring Boot 3.5快速接入大模型聊天与结构化输出

前几天想在现有的 Spring Boot 项目里加一个调用大模型聊天的功能。一开始的思路是直接用 RestClient 或者三方 SDK 去调模型接口,后来顺手试了试 Spring AI 这个官方生态,才发现它已经把大模型相关的接入、流式响应、结构化解析、提示词模板都包装成了 …

作者头像 李华
网站建设 2026/10/20 4:21:46

TortoiseGit推送报错密码认证已移除?用个人访问令牌PAT解决

1. 这个报错到底在说什么如果你在用 TortoiseGit 往远端仓库推送代码时,突然弹出一行英文提示:Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.,别慌,这不是你…

作者头像 李华