我新裝的centos7主機沒法使用裏面自帶的網卡,查詢後發現網卡型號爲BCM4312。我在看資料安裝的過程當中遇到了些問題,糾結了很久,如今分享下要注意的點,爲後來的遇到一樣問題的人提供點幫助。如今開始說正事:html
若要安裝以 Broadcom BCM43十一、BCM43十二、BCM431三、BCM432一、BCM432二、BCM4322四、BCM4322五、BCM43227 或 BCM43228 爲基礎的無線網絡卡,請遵守如下的步驟:node
首先,請肯定你是位「擁有 Broadcom BCM43xx 無線網絡卡的幸運兒」:linux
[user@host ~]$ /sbin/lspci | grep Broadcom 0b:00.0 Network controller: Broadcom Corporation BCM4312 802.11a/b/g (rev 01)
辨認完無線網絡芯片型號以後,請肯定你不會欠缺編譯及安裝時所需的組件:centos
[root@host]# yum install kernel-headers kernel-devel gcc
固然,倘若你要爲 Xen 內核(kernel-xen)編譯驅動程序,你必須安裝 kernel-xen-devel 而不是 kernel-devel。需不需安裝,推薦看下:http://blog.sina.com.cn/s/blog_946b3ae20100yxdm.htmlbash
請從Broadcom的官方網站(https://www.broadcom.com/)下載 Broadcom BCM43xx 的 linux 驅動程序壓縮檔到你的機器並將它解壓到 /usr/local/src/hybrid-wl,請隨你所需將這個目錄的擁有者改成無特權的用戶:(我下載的是hybrid-v35_64-nodebug-pcoem-6_30_223_271.tar.gz,把這個包放/usr/local/src/hybrid-wl這個目錄下,我以這個包寫的例子,你根據本身下的包來改動下面的語句。我選的無特權用戶爲nobody。)網絡
[root@host ~]# mkdir -p /usr/local/src/hybrid-wl [root@host hybrid-wl]# cd /usr/local/src/hybrid-wl [root@host hybrid-wl]# tar xvfz /usr/local/src/hybrid-wl/hybrid-v35_64-nodebug-pcoem-6_30_223_271.tar.gz [root@host hybrid-wl]# chown -R nobody.nobody /usr/local/src/hybrid-wl
注:爲何不隨便將它解壓到一個位置並保留缺省的擁有者?
緣由是上面的作法會把驅動模塊的源代碼保留在系統上 —— 在你放置它們的位置 —— 好讓你能夠隨時按須要建立驅動程序(譬如:你將內核升了級 —— 由於驅動模塊永遠根據某個內核來編譯),還有,就是你能夠用無特權的用戶來編譯!app
驅動模塊能夠這樣編譯:less
[user@host hybrid-wl]$ make -C /lib/modules/`uname -r`/build M=`pwd`
請留意引號(即反引號),centos官方的文檔寫的是[user@host hybrid-wl]$ make -C /lib/modules/`uname -r`/build/ M=`pwd`,我照作了,就是通不過,後來發現M前面的/是不須要的,加個空格就行。ide
編譯現有的驅動程序(6.30.223.271 版)時,你差很少確定會得到一個錯誤信息,而不是一個編譯好的驅動模塊網站
make: Entering directory `/usr/src/kernels/2.6.32-573.7.1.el6.x86_64'
CFG80211 API is prefered for this kernel version
Using CFG80211 API
LD /usr/local/src/hybrid-wl/built-in.o
CC [M] /usr/local/src/hybrid-wl/src/shared/linux_osl.o
CC [M] /usr/local/src/hybrid-wl/src/wl/sys/wl_linux.o
CC [M] /usr/local/src/hybrid-wl/src/wl/sys/wl_iw.o
CC [M] /usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.o
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:83: warning: ‘enum tx_power_setting’ declared inside parameter list
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:83: warning: its scope is only this definition or declaration, <snip>
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c: In function ‘wl_cfg80211_join_ibss’:
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:730: error: ‘struct cfg80211_ibss_params’ has no member named ‘channel’
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c: At top level:
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:1096: warning: ‘enum tx_power_setting’ declared inside parameter list
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:1096: error: parameter 2 (‘type’) has incomplete type
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c: In function ‘wl_cfg80211_set_tx_power’:
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:1107: error: ‘TX_POWER_AUTOMATIC’ undeclared (first use in this <snip>
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:1107: error: (Each undeclared identifier is reported only once
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:1107: error: for each function it appears in.)
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:1109: error: ‘TX_POWER_LIMITED’ undeclared (first use in this function)
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:1115: error: ‘TX_POWER_FIXED’ undeclared (first use in this function)
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c: At top level:
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:1774: warning: initialization from incompatible pointer type
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:1779: warning: initialization from incompatible pointer type
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:1780: warning: initialization from incompatible pointer type
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:1781: warning: initialization from incompatible pointer type
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:1782: warning: initialization from incompatible pointer type
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:1783: warning: initialization from incompatible pointer type
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:1784: warning: initialization from incompatible pointer type
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:1789: warning: initialization from incompatible pointer type
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c: In function ‘wl_inform_single_bss’:
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:1984: error: too few arguments to function <snip>
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:2023: warning: passing argument 1 of ‘cfg80211_put_bss’ from <snip>
include/net/cfg80211.h:3380: note: expected ‘struct wiphy *’ but argument is of type ‘struct cfg80211_bss *’
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:2023: error: too few arguments to function ‘cfg80211_put_bss’
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c: In function ‘wl_update_bss_info’:
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:2276: error: ‘struct cfg80211_bss’ has no member named <snip>
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:2277: error: ‘struct cfg80211_bss’ has no member named <snip>
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:2283: warning: passing argument 1 of ‘cfg80211_put_bss’ from <snip>
include/net/cfg80211.h:3380: note: expected ‘struct wiphy *’ but argument is of type ‘struct cfg80211_bss *’
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:2283: error: too few arguments to function ‘cfg80211_put_bss’
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c: In function ‘wl_bss_roaming_done’:
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:2322: warning: passing argument 2 of ‘cfg80211_roamed’ from <snip>
include/net/cfg80211.h:3726: note: expected ‘struct ieee80211_channel *’ but argument is of type ‘u8 *’
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:2322: warning: passing argument 4 of ‘cfg80211_roamed’ makes <snip>
include/net/cfg80211.h:3726: note: expected ‘const u8 *’ but argument is of type ‘s32’
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:2322: warning: passing argument 5 of ‘cfg80211_roamed’ makes <snip>
include/net/cfg80211.h:3726: note: expected ‘size_t’ but argument is of type ‘u8 *’
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:2322: warning: passing argument 6 of ‘cfg80211_roamed’ makes <snip>
include/net/cfg80211.h:3726: note: expected ‘const u8 *’ but argument is of type ‘s32’
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:2322: error: too few arguments to function ‘cfg80211_roamed’
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c: In function ‘wl_update_wowl’:
/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:2791: warning: unused variable ‘wdev’
make[1]: *** [/usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.o] Error 1
make: *** [_module_/usr/local/src/hybrid-wl] Error 2
make: Leaving directory `/usr/src/kernels/2.6.32-573.7.1.el6.x86_64'
注意: 在 EL6 和 EL7 的步驟由此起有分別。若是是 EL6,你應該聽從第 3 步上;而 EL7 只須應用第 3 步上的修正及第 3 步下的 sed 指命,並按照此步驟(3 上)內的指示編譯它。便是說, EL7 要略過第3步上的 sed 指令。
在 EL6 上,驅動程序因爲 wl_cfg80211_hybrid.c 檔內檢查內核版本的 if-then-else 句式而不能編譯。咱們需要執行下列的 sed 替換指令來進行修正:
。這則信息的內容隨着內核和操做系統版本而變化,可是在 CentOS 6 上它大體上是:
[user@host hybrid-wl]$ sed -i 's/[ >][>=] KERNEL_VERSION(2, 6, 3.)/>= KERNEL_VERSION(2, 6, 32)/' src/wl/sys/wl_cfg80211_hybrid.c [user@host hybrid-wl]$ sed -i 's/[ >][>=] KERNEL_VERSION(3, ., .)/>= KERNEL_VERSION(2, 6, 32)/' src/wl/sys/wl_cfg80211_hybrid.c [user@host hybrid-wl]$ sed -i 's/[ >][>=] KERNEL_VERSION(3, 11, .)/>= KERNEL_VERSION(2, 6, 32)/' src/wl/sys/wl_cfg80211_hybrid.c [user@host hybrid-wl]$ sed -i 's/< KERNEL_VERSION(3, 18, .)/< KERNEL_VERSION(2, 6, 30)/' src/wl/sys/wl_cfg80211_hybrid.c [user@host hybrid-wl]$ sed -i 's/[ >][>=] KERNEL_VERSION(3, 15, .)/>= KERNEL_VERSION(2, 6, 32)/' src/wl/sys/wl_cfg80211_hybrid.c [user@host hybrid-wl]$ sed -i 's/[ >][>=] KERNEL_VERSION(4, 0, 0)/>= KERNEL_VERSION(2, 6, 32)/' src/wl/sys/wl_cfg80211_hybrid.c [user@host hybrid-wl]$ sed -i 's/< KERNEL_VERSION(4,2,0)/< KERNEL_VERSION(2, 6, 30)/' src/wl/sys/wl_cfg80211_hybrid.c
不過,這些 'sed' 替換命令仍未能確保驅動程序能夠正常編譯。咱們還需要在編譯驅動程序前應用 wl-kmod-fix-ioctl-handling.patch 這個修正。請將它下載至 /usr/local/src 而後執行下列指令來修正驅動程序的源代碼:
[user@host hybrid-wl]$ patch -p1 < ../wl-kmod-fix-ioctl-handling.patch patching file src/wl/sys/wl_cfg80211_hybrid.c Hunk #1 succeeded at 1467 (offset 17 lines). patching file src/wl/sys/wl_linux.c Hunk #1 succeeded at 1659 (offset 8 lines).
如今,請嘗試再次編譯驅動模塊:
[user@host hybrid-wl]$ make -C /lib/modules/`uname -r`/build M=`pwd`
編譯器的輸出大體上是這樣:
make: Entering directory `/usr/src/kernels/2.6.32-573.7.1.el6.x86_64' CFG80211 API is prefered for this kernel version Using CFG80211 API LD /usr/local/src/hybrid-wl/built-in.o CC [M] /usr/local/src/hybrid-wl/src/shared/linux_osl.o CC [M] /usr/local/src/hybrid-wl/src/wl/sys/wl_linux.o CC [M] /usr/local/src/hybrid-wl/src/wl/sys/wl_iw.o CC [M] /usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.o /usr/local/src/hybrid-wl/src/wl/sys/wl_cfg80211_hybrid.c:1802: warning: initialization from incompatible pointer type LD [M] /usr/local/src/hybrid-wl/wl.o Building modules, stage 2. CFG80211 API is prefered for this kernel version Using CFG80211 API MODPOST 1 modules CC /usr/local/src/hybrid-wl/wl.mod.o LD [M] /usr/local/src/hybrid-wl/wl.ko.unsigned NO SIGN [M] /usr/local/src/hybrid-wl/wl.ko make: Leaving directory `/usr/src/kernels/2.6.32-573.7.1.el6.x86_64'
一旦這個模塊被建成,你即可以刪除沒必要要的符號:
[user@host hybrid-wl]$ strip --strip-debug wl.ko
你會發現驅動模塊的文件尺寸會縮小(由 8.2MB 降至 7.2MB)。並且,你的驅動模塊仍能正常運做。
許多中文資料都是這麼說的:
寫完這上面4個sed,再make,
[user@host hybrid-wl]$ make -C /lib/modules/`uname -r`/build M=`pwd`
就是通不過,後來找到centos WIKI 的英文原版資料才發現,中文翻譯的資料落後了,沒有及時跟新,中文資料只說到EL7.2的事,那EL7.3 即 kernel-3.10.0-514.X該怎麼寫呢?看英文怎麼說吧:
EL7.3 即 kernel-3.10.0-514.X 須要6個sed:
[user@host hybrid-wl]$ sed -i 's/ >= KERNEL_VERSION(3, 11, 0)/ >= KERNEL_VERSION(3, 10, 0)/' src/wl/sys/wl_cfg80211_hybrid.c [user@host hybrid-wl]$ sed -i 's/ >= KERNEL_VERSION(3, 15, 0)/ >= KERNEL_VERSION(3, 10, 0)/' src/wl/sys/wl_cfg80211_hybrid.c [user@host hybrid-wl]$ sed -i 's/ < KERNEL_VERSION(3, 18, 0)/ < KERNEL_VERSION(3, 9, 0)/' src/wl/sys/wl_cfg80211_hybrid.c [user@host hybrid-wl]$ sed -i 's/ >= KERNEL_VERSION(4, 0, 0)/ >= KERNEL_VERSION(3, 10, 0)/' src/wl/sys/wl_cfg80211_hybrid.c [user@host hybrid-wl]$ sed -i 's/ < KERNEL_VERSION(4,2,0)/ < KERNEL_VERSION(3, 9, 0)/' src/wl/sys/wl_cfg80211_hybrid.c [user@host hybrid-wl]$ sed -i 's/ >= KERNEL_VERSION(4, 7, 0)/ >= KERNEL_VERSION(3, 10, 0)/' src/wl/sys/wl_cfg80211_hybrid.c
別急,EL7.3先得裝個補丁,再跑上面的6個sed,補丁 wl-kmod-kernel_4.7_IEEE80211_BAND_to_NL80211_BAND.patch ,把它下好放到/usr/local/src 目錄下,運行補丁:
[user@host hybrid-wl]$ patch -p1 < /usr/local/src/wl-kmod-kernel_4.7_IEEE80211_BAND_to_NL80211_BAND.patch patching file src/wl/sys/wl_cfg80211_hybrid.c Hunk #6 succeeded at 1911 (offset 3 lines). Hunk #7 succeeded at 2040 (offset 3 lines). Hunk #8 succeeded at 2160 (offset 3 lines). Hunk #9 succeeded at 2298 (offset 3 lines). Hunk #10 succeeded at 2941 (offset 3 lines).
注意-p1中是數字1。打完了補丁,再輸6個sed,而後再make,
[user@host hybrid-wl]$ make -C /lib/modules/`uname -r`/build M=`pwd`
覺得就這樣成功了,並無,看:
找了半天,終於發現上圖小紅框中與centos wiki的教程不一樣,就多了兩個空格,仔細看,小紅框上面和下面的括號裏面都有空格,惟獨這個括號裏面就沒有空格,找到問題了,我再試試,終於跑通了。以下圖:
同時特別注意第3個和第5個sed中沒有等號,並且箭頭指向與其餘sed也不一樣。
當你成功地編譯了驅動模塊後,你即可以將它裝入內核中,並最終設置開機時自動裝入此驅動程序(要這樣作,你必須利用 root 的權限)。固然,作這一切之先,你必須從內核刪除如今的無線驅動模塊(假若有的話):
[root@host ~]# modprobe -r bcm43xx [root@host ~]# modprobe -r b43 [root@host ~]# modprobe -r b43legacy [root@host ~]# modprobe -r ssb [root@host ~]# modprobe -r bcma [root@host ~]# modprobe -r brcmsmac [root@host ~]# modprobe -r ndiswrapper
請將驅動模塊的文件複製到一個可讓內核找到它的地方:
[root@host hybrid-wl]# cp -vi /usr/local/src/hybrid-wl/wl.ko /lib/modules/`uname -r`/extra/
這樣作是爲了與其它已經/將會從 kmod 組件安裝的外置模塊(例如:fuse、ntfs-3g、等)保持一向性。按著,請執行:
[root@host ~]# depmod $(uname -r)
以便能建立一個模塊的互賴性清單。如今咱們裝入驅動模塊:
[root@host hybrid-wl]# insmod wl.ko
假如這一步失敗了(有很多這樣的報告,可是做者自己尚未遇到過這類問題),並伴有以下提示信息:
insmod: error inserting 'wl.ko': -1 Unknown symbol in module
首先嚐試建立模塊依賴:
[root@host ~]# depmod `uname -r`
而後裝入驅動模塊:
[root@host hybrid-wl]# modprobe wl
要是沒有錯誤信息,驅動程序已被裝入及隨時可用。假如你只有無線驅動程序應用 ndiswrapper 內核模塊,你可將它刪除 —— 但這並不是必須的。
你仍須額外數個步驟才能在開機時自動裝入模塊。首先,編輯 /etc/modprobe.d/blacklist.conf 這個文件並加入如下內容:
blacklist bcm43xx blacklist b43 blacklist b43legacy blacklist bcma blacklist brcmsmac blacklist ssb blacklist ndiswrapper
什麼?沒有找到/etc/modprobe.d/blacklist.conf,那咱們就本身寫一個(我用gedit寫的)取名叫做blacklist.conf,再放到那個目錄下就好了。
經過這樣作,你能夠防止這些模塊在開機時被裝入內核中,與 wl 模塊產生衝突。
另外,若要在開機時裝入 wl 模塊,請建立或者編輯/etc/sysconfig/modules/kmod-wl.modules並把如下內容剪貼到其中:
#!/bin/bash for M in lib80211 cfg80211 wl; do modprobe $M &>/dev/null done
如今你的驅動應該在每次開機時都會被裝入(固然除了在你安裝了新內核以後,到時你必須依照以上步驟將它從新編譯)。
操做完這些,我終於看到個人屏幕上出現了wifi的圖標:
好,那我再連個網試試,很是開心,主機可使用無線網卡上網了。
最後嘮叨一句,原版英文資料是最靠譜的。
參考資料1:https://wiki.centos.org/HowTos/Laptops/Wireless/Broadcom?action=show