资讯动态

Ubuntu下RTL8812BU无线网卡驱动编译安装与报错解决指南

发布时间:2026/9/25 1:20:43 来源:尧图企业网站定制
1. 为什么RTL8812BU在Ubuntu上总是不省心如果你手头有一个基于瑞昱RTL8812BU芯片的USB无线网卡插上Ubuntu之后大概率会遇到一个很尴尬的局面lsusb能看到设备但ip link里死活找不到对应的无线接口或者勉强识别出来却搜不到任何WiFi信号。这不是你的操作有问题而是这颗芯片在Linux主线内核里的支持一直处于“半吊子”状态——内核里确实有一个rtl8xxxu的通用驱动但它对8812BU的支持非常有限尤其是涉及5GHz频段和802.11ac高速率模式时基本处于不可用状态。我在过去两年里前后折腾过五六块不同厂商封装的8812BU网卡有带外置天线的“大块头”也有那种比指甲盖大不了多少的迷你款。它们的共同点是芯片方案一致但USB的VID/PID组合五花八门导致即使你编译好了驱动也可能因为设备ID不在白名单里而无法自动绑定。更麻烦的是瑞昱官方虽然提供了Linux驱动源码但代码质量参差不齐在不同内核版本上编译时踩坑几乎是必然事件。这篇文章要解决的问题很具体在Ubuntu环境下从源码编译并安装RTL8812BU驱动让网卡正常工作同时把编译过程中那些让人抓狂的报错逐个拆解掉。适合两类人看一是刚接触Linux驱动编译、手里正好有这块网卡的新手二是之前尝试过但被编译错误劝退、想搞清楚问题根源的老玩家。我会尽量把每一步的“为什么”讲清楚而不是只丢一堆命令让你照抄。需要提前说明的是驱动编译这件事和内核版本强相关。我下面演示的环境是Ubuntu 22.04 LTS内核版本5.15但我会把不同内核版本下可能遇到的差异也一并说明方便你对照自己的环境做调整。2. 动手之前先把这几件事确认清楚2.1 确认你的网卡芯片到底是不是RTL8812BU这一步听起来多余但实际上很多人手里的网卡是RTL8811CU、RTL8821CU或者RTL8812AU外观和8812BU几乎一样但驱动完全不通用。最可靠的确认方式是用lsusb命令查看USB设备IDlsusb你会看到类似这样的输出Bus 001 Device 004: ID 0bda:b812 Realtek Semiconductor Corp. RTL8812BU关键看ID后面的两段十六进制数0bda是瑞昱的厂商IDb812是8812BU的典型产品ID。如果你看到的是b8118811CU、c8118821CU或者88128812AU那后面的驱动源码选择就要换不能直接用8812BU的驱动。注意有些厂商会自己改PID比如某些品牌会把b812改成自己的编号。这种情况下你需要在驱动源码的os_dep/linux/usb_intf.c文件里手动添加设备ID后面我会具体讲怎么加。2.2 检查内核头文件和编译工具链是否齐全编译驱动需要内核头文件linux-headers和基本的编译工具gcc、make。Ubuntu桌面版默认可能没装全先用下面这条命令确认dpkg -l | grep linux-headers-$(uname -r)如果没有输出说明当前内核的头文件没装执行sudo apt update sudo apt install linux-headers-$(uname -r) build-essential git dkms这里我特意把dkms也加上了。DKMSDynamic Kernel Module Support的作用是当你后续更新内核时它会自动重新编译并安装这个驱动模块省得每次内核升级都要手动折腾一遍。对于这种第三方驱动来说DKMS几乎是必备的。2.3 先把内核自带的rtl8xxxu驱动拉黑Ubuntu内核里自带的rtl8xxxu模块会抢先绑定你的网卡导致你编译的驱动即使装好了也抢不到设备。所以第一步是把它加入黑名单echo blacklist rtl8xxxu | sudo tee /etc/modprobe.d/blacklist-rtl8xxxu.conf sudo modprobe -r rtl8xxxu执行完modprobe -r之后再用lsmod | grep rtl确认一下应该看不到rtl8xxxu了。这一步很多人会忘结果编译安装一切顺利但网卡就是不工作排查半天才发现是内核自带驱动在捣乱。3. 驱动源码的选择与获取3.1 为什么我不推荐直接用瑞昱官方源码瑞昱官方确实在GitHub上有一个rtl8812bu的仓库但那个仓库的代码更新频率很低而且对较新内核5.10以上的兼容性做得不好。我试过在5.15内核上直接编译官方源码遇到了一堆implicit declaration of function和unknown type name的错误改起来非常费劲。目前社区里维护得比较好的是aircrack-ng团队fork出来的版本以及一些个人维护者在官方代码基础上打了兼容性补丁的仓库。我实测下来比较稳的是morrownr/8812bu-20210702这个仓库它在5.4到6.2内核上都有人验证过可用。git clone https://github.com/morrownr/8812bu-20210702.git cd 8812bu-20210702如果你因为网络原因访问GitHub有困难也可以去国内的代码托管平台搜一下镜像关键词就是8812bu-20210702一般都能找到同步的副本。3.2 源码目录结构速览进入源码目录后你会看到几个关键文件夹core/驱动的核心逻辑包括802.11协议处理、加密、速率控制等hal/硬件抽象层8812BU的寄存器操作、射频校准都在这里os_dep/linux/Linux平台相关的适配代码USB接口绑定、网络设备注册都在这个目录下include/头文件编译之前你不需要改动大部分文件但有两个地方可能需要根据你的环境调整一个是Makefile里的内核路径另一个是os_dep/linux/usb_intf.c里的设备ID表。3.3 设备ID不在列表里怎么办前面提到有些厂商会改PID。如果你lsusb看到的ID不是0bda:b812就需要手动添加到驱动里。打开os_dep/linux/usb_intf.c找到rtw_usb_id_tbl这个数组在里面加一行{USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0xXXXX, 0xff, 0xff, 0xff)},其中0xXXXX换成你实际的PID。加完之后保存再继续后面的编译步骤。这个操作不复杂但如果你不知道要改这里就会陷入“驱动装好了但设备不识别”的困境。4. 编译过程中的五个典型报错与解决思路这一节是整篇文章的核心。我把过去两年里在不同内核版本上编译8812BU驱动时遇到的报错做了个汇总基本上覆盖了90%以上的情况。每个报错我都会先解释原因再给解决方案。4.1 报错一error: implicit declaration of function cfg80211_...这个报错通常出现在内核5.10及以上版本。原因是内核的cfg80211子系统在5.10之后修改了一些函数签名而驱动源码里还在用旧版的调用方式。具体报错信息一般长这样error: implicit declaration of function ‘cfg80211_roamed’; did you mean ‘cfg80211_roamed_bss’?解决办法是打开os_dep/linux/ioctl_cfg80211.c搜索报错里提到的函数名然后根据内核版本做条件编译。以cfg80211_roamed为例在5.10以上内核里应该替换为cfg80211_roamed_bss并且参数列表也要调整#if (LINUX_VERSION_CODE KERNEL_VERSION(5, 10, 0)) cfg80211_roamed_bss(ndev, bss, req_ie, req_ie_len, resp_ie, resp_ie_len, GFP_KERNEL); #else cfg80211_roamed(ndev, req_ie, req_ie_len, resp_ie, resp_ie_len, GFP_KERNEL); #endif这种条件编译的写法在驱动源码里很常见核心思路就是用LINUX_VERSION_CODE宏判断当前内核版本不同版本走不同的代码分支。你不需要把所有报错都一次性改完编译一次看一个报错改一个再编译这样效率反而更高。4.2 报错二error: struct net_device has no member named ...这个报错说明内核的网络设备结构体发生了变化。比如在5.15内核里net_device结构体的priv字段被移除了驱动里如果还在用ndev-priv就会报错。解决方式是改用netdev_priv(ndev)函数来获取私有数据/* 旧写法 */ adapter (PADAPTER)ndev-priv; /* 新写法 */ adapter (PADAPTER)netdev_priv(ndev);类似的字段变动还有trans_start、last_rx等这些在网络设备驱动里都是高频使用的字段。遇到这类报错时最快的办法是去内核源码里搜一下对应的结构体定义看看字段是不是改名了或者被移到了别的结构体里。4.3 报错三error: too few arguments to function ...函数参数数量不匹配通常是因为内核在某个版本里给某个函数增加了参数。比如proc_create在5.6内核里增加了parent参数timer_setup在4.15之后替代了init_timer。这类报错的解决思路和4.1类似也是用条件编译来处理。但有一点需要注意不要盲目地给函数补参数要先确认新增的参数是什么含义。比如proc_create新增的parent参数如果你不确定该传什么传NULL通常是可以的表示在/proc根目录下创建。4.4 报错四error: unknown type name bool或u8等类型未定义这个报错看起来很奇怪因为bool和u8都是内核里最基础的类型。出现这个问题的原因通常是头文件包含顺序不对或者某个头文件在新内核里被移除了。解决办法是在报错的源文件顶部加上#include linux/types.h #include linux/kernel.h如果加了之后还报错那就检查一下是不是Makefile里的ccflags-y缺少了必要的包含路径。正常情况下驱动源码的Makefile里会有类似这样的配置ccflags-y -I$(src)/include ccflags-y -DCONFIG_IOCTL_CFG80211确认这些配置没有被注释掉。4.5 报错五编译通过但insmod时报Unknown symbol这是最让人头疼的一类问题编译阶段一切正常make没有报任何错但当你执行sudo insmod 8812bu.ko时系统告诉你insmod: ERROR: could not insert module 8812bu.ko: Unknown symbol in module用dmesg | tail查看内核日志会看到类似Unknown symbol cfg80211_...的信息。这说明驱动依赖的某个内核符号在当前内核里不存在或者没有导出。解决步骤分两步先用modinfo 8812bu.ko查看驱动的依赖信息确认它依赖哪些模块用grep 符号名 /proc/kallsyms确认该符号是否存在于当前内核如果符号确实不存在那说明你的驱动源码和当前内核版本不匹配需要换一个更新版本的驱动源码或者把内核降级到驱动支持的版本。提示Unknown symbol问题在跨大版本内核编译时特别常见。比如你用为5.4内核写的驱动去编译到6.1内核上大概率会遇到这个问题。所以选驱动源码时尽量选最近半年内有更新的仓库。5. 安装、加载与验证的完整流程5.1 编译与安装的具体命令确认源码目录下的Makefile没有明显问题后直接执行make clean make -j$(nproc) sudo make installmake -j$(nproc)会用你CPU的所有核心并行编译速度比单线程快很多。编译完成后make install会把生成的8812bu.ko复制到/lib/modules/$(uname -r)/kernel/drivers/net/wireless/目录下并执行depmod更新模块依赖关系。如果你之前装了dkms也可以用DKMS的方式来安装这样后续内核升级时驱动会自动重新编译sudo dkms add . sudo dkms install -m 8812bu -v 1.0DKMS方式的好处是一劳永逸缺点是第一次配置稍微麻烦一点需要在源码目录里放一个dkms.conf文件。如果你只是临时用一下直接make install就够了。5.2 加载驱动并确认网卡识别sudo modprobe 8812bu然后检查内核日志dmesg | tail -20如果看到类似下面的输出说明驱动加载成功并且识别到了网卡[ 123.456789] usbcore: registered new interface driver rtl8812bu [ 123.567890] rtl8812bu 1-2:1.0: vendor request req_07 failed [ 123.678901] rtl8812bu 1-2:1.0: rtl8812bu driver version v5.13.1 [ 123.789012] rtl8812bu 1-2:1.0: wlan0: renamed from wlx...然后用ip link确认无线接口是否存在ip link show你应该能看到一个wlan0或者类似名称的接口。如果接口存在但状态是DOWN用sudo ip link set wlan0 up把它启用。5.3 用wpa_supplicant连接WiFi做最终验证接口起来了不代表能上网还需要验证驱动是否真的能收发数据。最直接的方式是用wpa_supplicant手动连接一个WiFisudo apt install wpasupplicant wpa_passphrase 你的WiFi名称 你的WiFi密码 | sudo tee /etc/wpa_supplicant.conf sudo wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant.conf sudo dhclient wlan0如果dhclient能成功获取到IP地址ping外网也通那说明驱动工作正常。如果wpa_supplicant报Failed to initialize driver interface那多半是驱动和cfg80211的对接还有问题需要回到第4节检查编译时的条件编译是否正确。6. 几个容易被忽略的细节和长期维护建议6.1 USB接口供电不足导致的随机断连8812BU在5GHz频段高速传输时功耗不低如果你用的是那种没有外接供电的USB Hub或者插在机箱前面的USB口上可能会遇到网卡随机掉线的问题。dmesg里会看到usb 1-2: reset high-speed USB device之类的信息。解决办法有两个一是直接插在主板后置的USB 3.0口上二是换一个带独立供电的Hub。这个问题和驱动无关但很容易被误判为驱动不稳定。6.2 内核升级后驱动失效的处理如果你没有用DKMS每次Ubuntu内核升级后之前编译的驱动模块都会失效因为模块是绑定到具体内核版本的。这时候你需要重新编译安装一遍。所以我还是建议花十分钟配置一下DKMS一劳永逸。配置DKMS的核心是创建一个dkms.conf文件内容大致如下PACKAGE_NAME8812bu PACKAGE_VERSION1.0 BUILT_MODULE_NAME[0]8812bu DEST_MODULE_LOCATION[0]/kernel/drivers/net/wireless AUTOINSTALLyes把这个文件放在源码根目录然后执行sudo dkms add .和sudo dkms install -m 8812bu -v 1.0即可。6.3 监控驱动状态的一个小技巧日常使用中如果想快速确认驱动和网卡的状态可以用这条命令sudo dmesg | grep -i rtl8812bu | tail -30它会过滤出所有和驱动相关的内核日志包括加载、固件下载、连接、断开等事件。遇到问题时这比盲目重启有效得多。6.4 关于5GHz频段和信道选择的经验8812BU在5GHz频段支持802.11ac但实际速率受信道宽度和干扰影响很大。我在家里测试时发现如果路由器把5GHz信道设在DFS频段比如52-64、100-140驱动有时会表现不稳定扫描能看到AP但连接困难。把路由器信道固定到36-48或者149-165这些非DFS频段后连接稳定性明显改善。这个经验不一定适用于所有环境但如果你遇到5GHz连接问题可以试试调整信道。6.5 驱动源码的版本管理建议如果你打算长期用这块网卡建议把编译好的驱动源码和dkms.conf一起放到一个固定的目录里比如/usr/src/8812bu-1.0然后用Git做版本管理。这样即使换了机器或者重装了系统也能快速恢复驱动环境。我自己是把整个源码目录放在~/drivers/8812bu下每次内核升级后如果DKMS自动编译失败就手动进去make clean make一遍通常都能解决。最后再分享一个排查思路当你遇到任何驱动相关的问题时先看dmesg再看lsusb最后看ip link。这三个命令基本能定位80%以上的问题。dmesg告诉你驱动加载时发生了什么lsusb确认硬件是否被系统识别ip link确认网络接口是否创建成功。按照这个顺序排查比漫无目的地搜索要高效得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价