卡驅(qū)動(dòng)編譯與避坑指南)
1. 為什么RTL8812BU在Ubuntu上總是不省心手里有一塊瑞昱RTL8812BU方案的USB無線網(wǎng)卡插上Ubuntu之后發(fā)現(xiàn)系統(tǒng)壓根不認(rèn)lsusb能看到設(shè)備但ip link里就是沒有對(duì)應(yīng)的無線接口——這個(gè)場景我遇到過太多次了。RTL8812BU是一顆雙頻AC 1200級(jí)別的USB 3.0無線芯片市面上大量USB網(wǎng)卡、天線延長底座、甚至一些迷你主機(jī)內(nèi)置模塊都在用它。性能不錯(cuò)價(jià)格便宜但Linux下的驅(qū)動(dòng)支持一直是個(gè)老大難問題內(nèi)核主線里沒有它的原生驅(qū)動(dòng)Ubuntu自帶的rtl8xxxu只能勉強(qiáng)識(shí)別部分老型號(hào)對(duì)8812BU的支持非常有限經(jīng)常出現(xiàn)能識(shí)別但連不上、或者連上后速率只有幾十兆的情況。這篇文章要解決的問題很具體在Ubuntu系統(tǒng)下讓RTL8812BU網(wǎng)卡正常工作并且把編譯驅(qū)動(dòng)過程中那些讓人抓狂的坑一次性講清楚。適合誰看手里有這類網(wǎng)卡、剛裝完Ubuntu發(fā)現(xiàn)沒WiFi、或者之前編譯失敗過想搞清楚原因的讀者。我會(huì)從驅(qū)動(dòng)方案選型開始一步步走到編譯、加載、驗(yàn)證中間穿插大量實(shí)際踩坑經(jīng)驗(yàn)保證你跟著做能跑通。先說一個(gè)基本判斷RTL8812BU在Linux下的驅(qū)動(dòng)目前最靠譜的方案是使用社區(qū)維護(hù)的rtl8812au驅(qū)動(dòng)分支注意不是8812au原版而是專門適配8812BU的aircrack-ng維護(hù)版本或者morrownr維護(hù)的版本。為什么不用Ubuntu自帶的因?yàn)樽詭?qū)動(dòng)對(duì)8812BU的芯片ID覆蓋不全而且缺少完整的802.11ac支持。自己編譯雖然麻煩但可控性最強(qiáng)出了問題也能自己排查。2. 驅(qū)動(dòng)方案選型與準(zhǔn)備工作2.1 三種驅(qū)動(dòng)來源的對(duì)比在動(dòng)手之前先搞清楚你有哪些選擇以及各自的優(yōu)缺點(diǎn)。我整理了一個(gè)對(duì)比表方便你根據(jù)自己情況決定方案來源優(yōu)點(diǎn)缺點(diǎn)適用場景內(nèi)核自帶rtl8xxxuUbuntu內(nèi)核免安裝插上就有對(duì)8812BU支持差速率低經(jīng)常斷流臨時(shí)應(yīng)急官方rtl8812au驅(qū)動(dòng)Realtek官網(wǎng)功能完整老對(duì)新內(nèi)核兼容差編譯報(bào)錯(cuò)多不推薦社區(qū)維護(hù)rtl8812au分支GitHub morrownr/rtl8812au-20210820持續(xù)更新支持新內(nèi)核8812BU適配好需要自己編譯推薦我實(shí)測下來morrownr維護(hù)的那個(gè)分支是目前最省心的。它把8812BU、8811CU、8821CU等一堆RTL88xxBU系列芯片的ID都合并進(jìn)去了而且針對(duì)5.x和6.x內(nèi)核做了大量適配。另一個(gè)aircrack-ng版本也可以但那個(gè)更偏向滲透測試場景會(huì)打監(jiān)控模式補(bǔ)丁日常使用反而可能引入不穩(wěn)定因素。2.2 編譯前必須確認(rèn)的三件事很多人編譯失敗不是驅(qū)動(dòng)本身的問題而是環(huán)境沒準(zhǔn)備好。動(dòng)手之前先確認(rèn)這三項(xiàng)第一確認(rèn)你的內(nèi)核版本。運(yùn)行uname -r記下輸出。比如6.5.0-35-generic。這個(gè)信息決定了你后面要不要額外打內(nèi)核兼容補(bǔ)丁。5.15以上的內(nèi)核DKMS方式基本都能自動(dòng)處理但如果你用的是6.8以上的新內(nèi)核有些老驅(qū)動(dòng)分支會(huì)報(bào)implicit-function-declaration錯(cuò)誤需要手動(dòng)改代碼。第二確認(rèn)你已經(jīng)裝了編譯工具鏈。最小依賴是build-essential、git、dkms以及當(dāng)前內(nèi)核對(duì)應(yīng)的頭文件linux-headers-$(uname -r)。缺頭文件是最常見的失敗原因報(bào)錯(cuò)通常是/lib/modules/xxx/build: No such file or directory。一條命令補(bǔ)齊sudo apt update sudo apt install -y build-essential git dkms linux-headers-$(uname -r)第三確認(rèn)Secure Boot狀態(tài)。如果你的主板開了Secure Boot編譯出來的第三方內(nèi)核模塊默認(rèn)會(huì)被拒絕加載modprobe會(huì)報(bào)Operation not permitted。要么進(jìn)BIOS關(guān)掉Secure Boot要么給模塊簽名。我一般建議直接關(guān)掉省事。檢查命令mokutil --sb-state輸出SecureBoot disabled就沒事如果是enabled要么關(guān)要么走簽名流程。提示如果你是在虛擬機(jī)里操作USB網(wǎng)卡需要先通過虛擬機(jī)軟件把設(shè)備直通給Ubuntu否則lsusb根本看不到。VMware在“虛擬機(jī)設(shè)置-USB控制器”里勾選對(duì)應(yīng)設(shè)備VirtualBox在“設(shè)備-USB”里掛載。2.3 確認(rèn)網(wǎng)卡芯片ID不是所有標(biāo)著“AC1200”的網(wǎng)卡都是8812BU有些是8811CU或者8821CU。插上網(wǎng)卡運(yùn)行l(wèi)susb | grep -i realtek你會(huì)看到類似ID 0bda:b812 Realtek Semiconductor Corp.的輸出。b812就是8812BU的典型PID。常見的對(duì)應(yīng)關(guān)系b812是8812BUc811是8811CUb82c是8821CU。記下你的ID后面驗(yàn)證驅(qū)動(dòng)是否匹配時(shí)要用。3. 編譯實(shí)操從克隆到加載的完整流程3.1 獲取驅(qū)動(dòng)源碼我推薦用morrownr的倉庫直接克隆cd /usr/src sudo git clone https://github.com/morrownr/rtl8812au-20210820.git為什么放在/usr/src因?yàn)镈KMS默認(rèn)會(huì)去這個(gè)目錄找源碼放這里后面注冊(cè)DKMS最順。克隆完成后進(jìn)去看一眼目錄結(jié)構(gòu)確認(rèn)有dkms-install.sh這個(gè)腳本有就說明是支持DKMS的版本。如果你網(wǎng)絡(luò)環(huán)境拉GitHub慢也可以先在其他機(jī)器下載zip包再傳過去解壓到/usr/src下同樣可以。3.2 用DKMS方式安裝推薦DKMS的好處是內(nèi)核升級(jí)后驅(qū)動(dòng)會(huì)自動(dòng)重新編譯不用你每次手動(dòng)折騰。這是我最推薦的方式。進(jìn)入源碼目錄直接跑安裝腳本cd /usr/src/rtl8812au-20210820 sudo ./dkms-install.sh這個(gè)腳本背后做的事把源碼注冊(cè)到DKMS、編譯、安裝模塊、加載。整個(gè)過程大概一到兩分鐘。如果一切順利你會(huì)看到Module installed successfully之類的提示。但現(xiàn)實(shí)往往沒那么順。下面是我遇到過的幾個(gè)典型報(bào)錯(cuò)和解決辦法。3.3 編譯報(bào)錯(cuò)排查三個(gè)高頻坑坑一error: implicit declaration of function cfg80211_...這個(gè)錯(cuò)誤通常出現(xiàn)在內(nèi)核6.5以上。原因是新內(nèi)核改了cfg80211子系統(tǒng)的函數(shù)簽名老驅(qū)動(dòng)沒跟上。解決辦法是打補(bǔ)丁。morrownr的倉庫其實(shí)已經(jīng)處理了大部分但如果你用的是更老的fork就需要手動(dòng)改。具體做法是找到報(bào)錯(cuò)的文件和行號(hào)對(duì)照新內(nèi)核的頭文件改參數(shù)。比如cfg80211_roamed在新內(nèi)核里參數(shù)變了需要把調(diào)用處改成新簽名。坑二error: ‘struct timer_list’ has no member named ‘data’內(nèi)核5.15之后timer_list結(jié)構(gòu)體去掉了data成員改用from_timer宏。這個(gè)錯(cuò)誤在8812au驅(qū)動(dòng)里很常見。修改方法把原來的timer.data相關(guān)代碼替換成from_timer方式。具體代碼改動(dòng)比較細(xì)建議直接換用已經(jīng)適配好的分支比如morrownr的20210820版本就已經(jīng)修好了??尤齧odprobe: ERROR: could not insert 88XXau: Required key not available這就是Secure Boot在作祟。兩個(gè)選擇關(guān)Secure Boot或者簽名。簽名流程稍微麻煩需要生成密鑰、導(dǎo)入MOK、簽名模塊這里不展開。最直接的辦法是重啟進(jìn)BIOS關(guān)掉Secure Boot。注意如果你之前用apt裝過rtl8812au-dkms這個(gè)包先卸載掉否則會(huì)和手動(dòng)編譯的版本沖突。命令sudo apt remove rtl8812au-dkms。3.4 手動(dòng)編譯方式DKMS失敗時(shí)的備選如果DKMS腳本跑不通可以手動(dòng)編譯。流程是cd /usr/src/rtl8812au-20210820 sudo make clean sudo make sudo make install sudo modprobe 88XXaumake這一步如果報(bào)錯(cuò)仔細(xì)看錯(cuò)誤信息基本都是內(nèi)核兼容問題。手動(dòng)編譯的好處是錯(cuò)誤信息更直接方便定位。缺點(diǎn)是內(nèi)核升級(jí)后要重新來一遍。3.5 驗(yàn)證驅(qū)動(dòng)是否加載成功加載之后用這幾條命令驗(yàn)證lsmod | grep 88XXau ip link show iw devlsmod能看到88XXau說明模塊加載了。ip link里應(yīng)該多出一個(gè)wlanX接口。iw dev能看到接口的詳細(xì)信息包括支持的頻段和模式。如果ip link里沒有新接口但lsmod有模塊那可能是芯片ID沒匹配上需要檢查驅(qū)動(dòng)的ID表里有沒有你的PID。我遇到過一種情況模塊加載了但接口名是wlan0卻顯示DOWN狀態(tài)。這時(shí)候運(yùn)行sudo ip link set wlan0 up如果報(bào)Operation not permitted多半是rfkill軟阻塞用rfkill list查看rfkill unblock wifi解鎖。4. 常見問題與排查技巧實(shí)錄4.1 網(wǎng)卡識(shí)別了但搜不到WiFi這是最典型的問題。iw dev能看到接口但nmcli dev wifi list空空如也。原因通常有三個(gè)一是驅(qū)動(dòng)雖然加載了但固件沒加載成功二是信道被管制域限制三是接口被rfkill阻塞。排查順序先dmesg | grep -i 88XXau看內(nèi)核日志有沒有firmware相關(guān)的報(bào)錯(cuò)。8812BU需要rtl8812bu_fw.bin這個(gè)固件文件通常在/lib/firmware/rtlwifi/下。如果沒有從驅(qū)動(dòng)源碼的firmware目錄復(fù)制過去。然后檢查rfkill list確認(rèn)沒有軟阻塞。最后看管制域iw reg get如果顯示country 00說明沒設(shè)置用sudo iw reg set CN設(shè)置一下。4.2 連接后速率只有幾十兆8812BU是AC1200理論速率867Mbps5G頻段。如果你連上后iw dev wlan0 link顯示速率只有54Mbps或者更低大概率是連到了2.4G頻段或者驅(qū)動(dòng)協(xié)商有問題。先確認(rèn)連的是5G AP然后檢查iw dev wlan0 link里的bitrate字段。如果5G下還是低速率可能是驅(qū)動(dòng)版本太老換最新分支重新編譯。另一個(gè)隱藏原因是USB接口速率。8812BU需要USB 3.0才能跑滿如果你插在USB 2.0口上上限就是480Mbps實(shí)際吞吐也就200Mbps左右。檢查方法lsusb -t看設(shè)備掛在哪個(gè)總線上5000M才是USB 3.0。4.3 內(nèi)核升級(jí)后驅(qū)動(dòng)失效這是DKMS方式也會(huì)遇到的問題新內(nèi)核的頭文件還沒裝DKMS自動(dòng)編譯失敗。解決辦法很簡單升級(jí)內(nèi)核后先裝頭文件sudo apt install linux-headers-$(uname -r) sudo dkms autoinstalldkms autoinstall會(huì)重新編譯所有注冊(cè)過的模塊。如果還是失敗dkms status看具體哪個(gè)模塊報(bào)錯(cuò)進(jìn)源碼目錄手動(dòng)make一次看詳細(xì)錯(cuò)誤。4.4 常見問題速查表現(xiàn)象可能原因解決命令/操作lsusb有設(shè)備但無wlan接口驅(qū)動(dòng)未加載或ID不匹配檢查lsmod確認(rèn)驅(qū)動(dòng)ID表含你的PID模塊加載報(bào)Required key not availableSecure Boot開啟關(guān)閉Secure Boot或簽名模塊接口存在但搜不到WiFi固件缺失或rfkill阻塞復(fù)制固件rfkill unblock wifi速率低USB 2.0或連了2.4G換USB 3.0口確認(rèn)5G連接內(nèi)核升級(jí)后失效頭文件未裝裝headers后dkms autoinstall編譯報(bào)timer_list錯(cuò)誤內(nèi)核5.15不兼容換用已適配分支4.5 幾個(gè)我踩過的坑第一個(gè)坑不要同時(shí)裝多個(gè)版本的8812au驅(qū)動(dòng)。我有一次先apt裝了rtl8812au-dkms又手動(dòng)編譯了一個(gè)結(jié)果兩個(gè)模塊搶設(shè)備時(shí)好時(shí)壞。后來全部卸載只留一個(gè)手動(dòng)編譯的才穩(wěn)定。第二個(gè)坑make install之后忘了depmod。有些老教程只寫make install但沒寫depmod -a導(dǎo)致模塊依賴關(guān)系沒更新modprobe找不到模塊。加上sudo depmod -a再modprobe就好了。第三個(gè)坑虛擬機(jī)里USB直通后如果虛擬機(jī)重啟USB設(shè)備可能沒自動(dòng)掛載回去需要重新在虛擬機(jī)設(shè)置里勾選。這個(gè)不是驅(qū)動(dòng)問題但很容易誤判。5. 長期維護(hù)與自動(dòng)化建議5.1 用DKMS實(shí)現(xiàn)內(nèi)核升級(jí)自動(dòng)重編前面已經(jīng)用了DKMS這里再強(qiáng)調(diào)一下它的價(jià)值。DKMS會(huì)在/var/lib/dkms/下維護(hù)模塊狀態(tài)每次內(nèi)核更新dkms autoinstall會(huì)自動(dòng)觸發(fā)重編。你唯一要保證的是新內(nèi)核的頭文件已經(jīng)安裝。可以寫一個(gè)簡單的apt鉤子讓內(nèi)核升級(jí)時(shí)自動(dòng)裝頭文件但更簡單的做法是養(yǎng)成習(xí)慣每次apt upgrade看到內(nèi)核更新手動(dòng)跑一次sudo apt install linux-headers-$(uname -r) sudo dkms autoinstall。5.2 備份可用驅(qū)動(dòng)版本社區(qū)驅(qū)動(dòng)更新頻繁有時(shí)候新版本反而引入回歸。我的做法是當(dāng)前穩(wěn)定可用的版本把整個(gè)源碼目錄打包備份一份。命令sudo tar czf rtl8812au-stable.tar.gz /usr/src/rtl8812au-20210820下次如果更新后出問題解壓回去重新dkms-install.sh就能回滾。這個(gè)習(xí)慣幫我省過好幾次重裝系統(tǒng)的時(shí)間。5.3 監(jiān)控驅(qū)動(dòng)狀態(tài)的小腳本我寫了一個(gè)簡單的檢查腳本放在~/check_wifi.sh每次覺得網(wǎng)絡(luò)不對(duì)勁就跑一下#!/bin/bash echo USB設(shè)備 lsusb | grep -i realtek echo 模塊狀態(tài) lsmod | grep 88XXau echo 接口狀態(tài) ip link show | grep wlan echo 連接信息 iw dev 2/dev/null | grep -E Interface|ssid|channel echo rfkill rfkill list這個(gè)腳本能快速定位問題出在哪一層是USB沒識(shí)別、模塊沒加載、還是接口沒起來。比一條條敲命令快得多。5.4 關(guān)于替代方案的思考如果你實(shí)在不想折騰編譯還有一個(gè)選擇換一塊內(nèi)核原生支持的網(wǎng)卡。比如基于MT7921或者AX210的網(wǎng)卡Linux內(nèi)核直接支持插上就能用。但如果你手頭已經(jīng)有8812BU或者需要它的特定功能比如外置天線、監(jiān)控模式那編譯驅(qū)動(dòng)還是值得的。我自己的主力機(jī)上就是8812BU編譯一次之后用DKMS維護(hù)一年多沒出過問題。最后分享一個(gè)判斷驅(qū)動(dòng)是否真正穩(wěn)定的方法連續(xù)跑iperf3打流半小時(shí)同時(shí)ping網(wǎng)關(guān)看延遲抖動(dòng)。如果速率穩(wěn)定、延遲沒有周期性尖峰說明驅(qū)動(dòng)和固件配合良好。如果每隔幾秒就卡一下多半是電源管理在搗亂可以在/etc/modprobe.d/下加一個(gè)配置文件禁用USB自動(dòng)掛起echo options 88XXau rtw_power_mgnt0 rtw_enusbss0 | sudo tee /etc/modprobe.d/88XXau.conf然后重新加載模塊。這個(gè)參數(shù)關(guān)掉了驅(qū)動(dòng)的省電模式對(duì)穩(wěn)定性提升很明顯代價(jià)是待機(jī)功耗略高臺(tái)式機(jī)無所謂筆記本自己權(quán)衡。