一、e1000网卡驱动
linux内核经常涉及编译某一项驱动代码的场景,本次以网卡驱动e1000为例说明整个步骤流程。
首先编译内核驱动不必要编译整个内核,但编译的驱动代码必须要和要安装的内核版本保持一致,否则经常会出现无法加载模块。
在编译驱动前,最好要保证3个版本一致:
1.`uname -r`当前系统内核版本 ----为了能够安装到本系统
2.yum install kernel-devel 版本 ----kernel-devel保证编译驱动时kernel的源码
3.某驱动src版本 ----保证编译时不会出现编译错误
1.当前系统版本
这个没什么好说的,直接按照当前系统的kernel版本统一即可,毕竟编译后的驱动时安装到本系统的,本次统一为4.18.0-348版本。
2.kernel-devel
注意kernel-devel版本一定要和当前系统本身kernel版本一致,这样编译后的驱动模块才能顺利安装。
在安装完kernel-devel后,系统会在/lib/modules/下自动创建kernel的目录,该目录下有个build软连接,指向/usr/src/`uname -r`/下的kernel源码目录,这个目录也是我们后期单独编译驱动时,make命令中-C选项指定的内核源码目录。
3.驱动源码e1000
本次intel 网卡驱动e1000的代码是从kernel-4.18.0-348.el8.src.rpm解压后的kernel-4.18.0中单独拷贝出来。
rpm -i kernel-4.18.0-348.el8.src.rpm后会在当前用户家目录下生成rpmbuild目录,将其中的linux-.tar.xz解压后,在kernel源码/drivers/net/ethernet/intel/e1000/拷贝出e1000驱动的源码文件到/root下。
4.编译驱动
原始的e1000源码由于是在kernel中整体构建,所以其自带的Makefile中没有可构建的目标,所以我们需要改动下Makefile,让其有具体的target为编译e1000.o
修改后的makefile如下,所有驱动源码单独编译时的Makefile均可用此模板,只需要修改modname以及相应的.o组成文件:
# cat e1000/Makefile
MODNAME = e1000
PWD = $(shell pwd)
KDIR ?= /lib/modules/$(shell uname -r)/build
obj-m += $(MODNAME).o #有时候MODNAME识别不了,则直接用原始名字即可
$(MODNAME)-y = \
e1000_main.o \
e1000_hw.o \
e1000_ethtool.o \
e1000_param.o
all:
make -C $(KDIR) M=$(PWD) src=$(PWD) modules #复制的话可能会使Tab变成空格,记得修改
clean:
make -C $(KDIR) M=$(PWD) src=$(PWD) clean
修改好Makefile后,就可以直接make编译了
编译后insmod或modprobe完成加载
二、Intel 新版本网卡驱动:ixgbe(网卡型号I210或82599ES)
在目前较新的Linux系统中,基本都不在自动编译e1000的网卡,因为太老旧了,现在基本都是10-Gigabit甚至更高速率的网卡,本轮以kernel-5.18版本驱动Intel 82599ES为例。
在编译kernel时,只要不用 make menuconfig 主动更改内核编译配置项,Intel网卡驱动ixgbe是自动编译的,具体路径在/drivers/net/ethernet/intel/ixgbe/ixgbe.ko,但在安装改驱动时就会发现,ixgbe.ko会依赖于另一个mdio.ko,其具体路径在/drivers/net/mdio.ko。
具体依赖哪个ko可以在安装该ko时的报错,或者用modinfo查看:
所以直接拷贝这两个ko直接去加载就可以驱动起网卡。在一些商业开发环境中,有时受限于内存大小等原因,需要把一些驱动直接打包放到initramfs中,在硬件机器上去加载。所以这就需要把两个ko直接打包到initramfs中,具体的initramfs根文件系统制作就是busybox那一套,详细可参考利用QEMU+GDB搭建Linux内核调试环境-云社区-华为云,写的很详细。
打包完成后可以直接跟kernel一起启动机器,此处我是启动的arm虚拟机:
/home/jcf/qemu-6.2.0/build/qemu-system-aarch64 -machine virt,accel=kvm,gic-version=3 -cpu host -m 8G -smp 4 -kernel /home/jcf/linux-5.18/arch/arm64/boot/Image.gz -initrd /home/jcf/initramfs.cpio.gz -append "debug rdinit=/init console=ttyAMA0" -device vfio-pci,host=0006:01:00.0,id=net0 -nographic
在系统起来后insmod驱动,加载完驱动后就可以发现系统多了张网卡。
目前网卡没有配置ip等,接下来可以手动配置ip,也可以通过配置文件配置。此处介绍下配置方法。首先由于是配置文件,是要提前写好并打包进initramfs中的,所以先基于网卡名字和类型准备好该网卡的配置文件:
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
NAME=eth0
DEVICE=eth0
ONBOOT=yes
IPADDR=10.100.6.66
GATEWAY=10.100.6.254
DNS1=8.8.8.8
DNS2=223.5.5.5
在某些情况下笔者发现配置ip后无法ping通其他设备,具体原因未知,最后经由命令ifup ethxx才搞定,一开始是报错缺文件:
于是又打包这个文件到initramfs,文件路径保持不变,文件内容酌情修改:
auto eth0
iface eth0 inet static
address 10.100.6.66
netmask 255.255.255.0
gateway 10.100.6.254
然后直接用命令“ifup eth0”启动网卡,这时发现可以ping通了。