1. 程式人生 > >第二十二期 OpenWrt 原理和結構分析《路由器就是開發板》

第二十二期 OpenWrt 原理和結構分析《路由器就是開發板》

https://blog.csdn.net/aggresss/article/details/52752529

這一期我們來真正的接觸OpenWrt,這個接觸是從原始碼方面的,不是刷機後通過web登入配置的那種。Wrt(Wireless RouTer)的歷史和文化大家可以自行搜尋一下,很有趣的。
        當Linksys釋放 WRT54G/GS 的原始碼後,網上出現了很多不同版本的 Firmware 去增強原有的功能。大多數的 Firmware 都是99%使用 Linksys的原始碼,只有1%是加上去的,每一種 Firmware 都是針對特定的市場而設計,這樣做有兩個缺點:第一個是難以集合各版本Firmware的長處;第二個是這版本距離 Linux 正式發行版越來越遠。OpenWrt 選擇了另一條路,它從零開始,一點一點的把各軟體加入進去,使其接近 Linksys 版 Firmware的功能,而OpenWrt 的成功之處是它的檔案系統是可寫的,開發者無需在每一次修改後重新編譯,令它更像一個小型的 Linux 電腦系統。所有我們可以這樣理解,OpenWrt不是一個路由器韌體,而是一種linux的發行版,和Ubuntu或者Fedora一樣,當然,我覺得它的風格更像ArcLinux。OpenWrt作為linux發行版理解的話,它的一個特點就是大多執行在啞裝置上(就是沒有直接顯示裝置的裝置)。
        在OpenWrt的官網 http://wiki.openwrt.org/ 上可以瞭解到很多與其相關的基礎知識, http://wiki.openwrt.org/doc/start 這個是文件入口,很詳細。
        先從獲取程式碼開始,這裡以15.05版本為例,使用git工具獲取原始碼:  git clone git://git.openwrt.org/15.05/openwrt.git  
        原始碼下載成功後在目錄下會生成十幾個資料夾,這些資料夾的作用在下面列出:
OpenWrt原始碼目錄結構:
tools和toolchain目錄:包含了一些通用命令, 用來生成韌體, 編譯器, 和C庫.
build_dir/host目錄:是一個臨時目錄, 用來儲存不依賴於目標平臺的工具.
build_dir/toolchain-目錄:用來儲存依賴於指定平臺的編譯鏈. 只是編譯檔案存放目錄無需修改.
build_dir/target-目錄:用來儲存依賴於指定平臺的軟體包的編譯檔案, 其中包括linux核心, u-boot, packages, 只是編譯檔案存放目錄無需修改.
staging_dir目錄:是編譯目標的最終安裝位置, 其中包括rootfs, package, toolchain.
package目錄:軟體包的下載編譯規則, 在OpenWrt韌體中, 幾乎所有東西都是.ipk, 這樣就可以很方便的安裝和解除安裝.
target目錄:目標系統指嵌入式裝置, 針對不同的平臺有不同的特性, 針對這些特性, "target/linux"目錄下按照平臺進行目錄劃分, 裡面包括了針對標準核心的補丁, 特殊配置等.
bin目錄:編譯完OpenWrt的二進位制檔案生成目錄, 其中包括sdk, uImage, u-boot, dts, rootfs構建一個嵌入式系統完整的二進位制檔案.
config目錄:存放著整個系統的的配置檔案.
docs目錄:裡面不斷包含了整個宿主機的檔案原始碼的介紹, 裡面還有Makefile為目標系統生成docs.
include目錄:裡面包括了整個系統的編譯需要的標頭檔案, 但是是以Make進行連線的.
feeds目錄:擴充套件軟體包索引目錄.
feeds/packages目錄:為執行./scripts/feeds install 之後的package。
scripts目錄:組織編譯整個OpenWrt的規則.
tmp目錄:編譯資料夾, 一般情況為空.
dl目錄:所有軟體的下載目錄, 包括u-boot, kernel.
logs目錄:如果編譯出錯, 可以在這裡找到編譯出錯的log.


        我這裡介紹一下OpenWrt相關的兩個概念feeds和buildroot,同時它們也是OpenWrt引進的兩種構建和編譯程式碼的機制,如果不瞭解這兩個概念很容易搞得一頭霧水。


Feeds:

        傳統的Linux系統在安裝或者編譯某一個軟體的時候,會檢查其依賴庫是否安裝,如果沒有安裝,則會報錯,安裝或編譯退出。這種機制使得開發者在安裝一個軟體之前,不得不查詢該軟體所需的依賴庫,並手動去安裝這些軟體,有時候碰到比較嬌貴的軟體時,巢狀式的安裝依賴檔案,會使得開發者頭昏腦漲。Openwrt通過引入feeds機制,較好的解決了這個問題。下文是Openwrt的官方wiki對於feeds的表述:
        "In OpenWrt, a "feed" is a collection of packages which share a common location. Feeds may reside on a remote server, in a version control system, on the local filesystem, orin any other location addressable by a single name (path/URL) over a protocol with a supported feed method.Feeds are additional predefined package build recipes for OpenWrt Buildroot".
        可以翻譯為:在Openwrt系統中,“feed”是一系列的軟體包,這些軟體包需要通過一個統一的介面地址進行訪問。“feed”軟體包中的軟體包可能分佈在遠端伺服器上、在svn上、在本地檔案系統中或者其他的地方,使用者可以通過一種支援feed機制的協議,通過同一個地址進行訪問。
        我們下載的Openwrt原始碼是較為純淨的系統,feeds提供了我們在編譯韌體時所需的的許多額外擴充套件軟體。我的理解是Feeds是OpenWRT環境所需要的軟體包套件,它將一個或一組軟體封裝成一個feeds,這樣做的好處就是OpenWrt成為了一個模組化的軟體,如果我們想讓它成為路由器就載入路由器相關的feeds,想讓他成為讀卡器就載入讀卡器相關的feeds。比較重要的feeds有:pacakges,LuCI,routing,telephony,management,這些都是預設的可以通過修改feeds.conf.default檔案進行配置。
         如果你之前沒有下載好這些套件,而是選擇在編譯的時候線上下載安裝的話,一定要保證編譯的時候是成功連線到網際網路的,否則導致編譯終端,出現“No More Mirrors Download”的錯誤很煩人的。為了避免其他的錯誤,還是在連線網際網路的情況下來編譯吧,編譯的過程本來就很長了,再出現這些錯誤會抓狂的。
下載之前可以通過檢視更改feeds.conf.default這個檔案來檢視和選擇相應的軟體包。
開始下載,使用命令:
./scripts/feeds update -a
接下來安裝feeds包,只有安裝之後,在make menuconfig的時候才能夠對相關的配置進行修改:
./scripts/feeds install -a
如果更新了feeds的配置檔案,需要新增新的軟體包用於生成系統,只需要重複執行操作:
./scripts/feeds update -a
./scripts/feeds install -a
將可使用的feeds列表配置在feeds.conf或者是feeds.conf.default,這個檔案包含了feeds的列表,每一行由三個部分組成,feeds的方法,feeds的名字和feeds的源。
下面是一個feeds.conf.default的例子:
src-git packages https://github.com/openwrt/packages.git;for-15.05
src-git luci https://github.com/openwrt/luci.git;for-15.05
src-git routing https://github.com/openwrt-routing/packages.git;for-15.05
src-git telephony https://github.com/openwrt/telephony.git;for-15.05
src-git management https://github.com/openwrt-management/packages.git;for-15.05
#src-git targets https://github.com/openwrt/targets.git
#src-git oldpackages http://git.openwrt.org/packages.git
#src-svn xwrt http://x-wrt.googlecode.com/svn/trunk/package
#src-svn phone svn://svn.openwrt.org/openwrt/feeds/phone
#src-svn efl svn://svn.openwrt.org/openwrt/feeds/efl
#src-svn xorg svn://svn.openwrt.org/openwrt/feeds/xorg
#src-svn desktop svn://svn.openwrt.org/openwrt/feeds/desktop
#src-svn xfce svn://svn.openwrt.org/openwrt/feeds/xfce
#src-svn lxde svn://svn.openwrt.org/openwrt/feeds/lxde
#src-link custom /usr/src/openwrt/custom-feed
下面是feeds支援的方法型別:
src-bzr通過使用bzr從資料來源的pxiaath/URL下載資料
src-cpy通過從資料來源path拷貝資料
src-darcs通過使用darcs從資料來源path/URL下載資料
src-hg通過使用hg從資料來源path/URL下載資料
src-link建立一個數據源path的symlink
src-svn通過使用svn從資料來源path/URL下載資料


Buildroot:


          Buildroot是一個包含Makefile和修補程式(patch)的集合,這個集合可以使你很容易的為你的目標構建交叉工具鏈(cross-compilationtoolchain),根檔案系統(root filesystem)以及Linux核心映像(kernelimage)。Buildroot可以獨立的實現其中的一個或幾個功能。
       Buildroot對於從事嵌入式系統(embeddedsystems)開發的人很有幫助。通常嵌入式系統使用的處理器(processor)同於在PC跑的x86架構的CPU。嵌入式系統可以使用IBM公司的PowerPC,可以是RISC指令的MIPS(包括龍芯II),也可以是ARM處理器,等等。
       編譯工具鏈(compilationtoolchain)是為你的作業系統編譯程式的工具的集合。主要包括編譯器(compiler)(比如說gcc),包括彙編器(assembler)和連結器(linker)的二進位制工具集(binaryutils)(在我們的Linux系統中通常為binutils),C標準類庫(比如GNU Libc、uClibc或者dietlibc)。
       你用來做開發的電腦上安裝的OS通常已經包含一個預設的編譯工具鏈,通過它便已出來的程式可以在你的系統上執行。如果當你使用PC,你的編譯工具鏈工作在x86架構的處理器上,產生的程式也是在x86處理器上使用的。在大多數Linux系統中,交叉工具鏈採用GNU libc(glibc)作為標準類庫。這種編譯工具鏈通常被稱為“主機編譯工具鏈(hostcompilation toolchain)”。你用來做開發工作的電腦上跑的系統被稱作“主機系統(hostsystem)”。這個編譯工具鏈由你的Linux發行版(distribution)的作業系統自帶,而Buildroot則於你的作業系統無關(但使用Buildroot建立的交叉工具鏈和其他工具可以在你的主機系統執行)。
       正如前面所述,編譯工具鏈由你的系統所提供,執行在你的系統上,產生你係統所用處理器可以執行的程式碼檔案。由於你的嵌入式系統的處理器通常與你的開發主機不同,你需要一個交叉編譯工具鏈,這工具鏈執行在你的開發主機上,但產生你的嵌入式目標主機(目標處理器)的可執行程式碼。比如你的開發主機系統採用x86處理器,而你的嵌入式目標系統處理器是ARM的,普通的編譯工具鏈在你的開發主機上只能產生x86處理器的執行程式碼,而交叉編譯工具鏈則可以在你的開發主機上產生ARM處理器的可執行程式碼。
       Buildroot自動使用所用可能用到的工具(比如busybox)構建根檔案系統。與手動操作相比,更容易。
       由於你可以手動使用gcc、binutils、uClibc和其他工具進行編譯,你一定很好奇為什麼非得用Buildroot這個工具呢。你當然可以使用手動設定,但處理每一個配置選項以及由gcc或binutils版本所產生問題都是非常耗時和無聊的。Buildroot通過使用Makefile自動處理這些問題,而且還對任一個gcc和binutils版本都有補丁集合以使得它可以在大多數Linux版本中工作。
       此外,Buildroot裡面提供了一個基礎結構,用於再現你構建核心交叉工具鏈和嵌入式根檔案系統的過程。當需要補丁、更新或當其他人接手這個專案時,構建過程能夠重現是很有用處的。
        OpenWrt的編譯過程引入了Buildroot的機制,對於不同平臺的host和target編譯過程變得非常簡單,Buildroot是一個開源的專案,https://buildroot.org/ 可以瞭解更多內容,OpenWrt對Buildroot進行了很多修改。Buildroot可以將我們嵌入式開發過程中遇到的幾個關鍵節點一站式解決,包括:SDK,Toolchain,U-Boot,Kernel,Rootfs,Imagebuilder 等等。
        關於OpenWrt的編譯流程我們留到下一期講解,這裡我再講一個常見的問題,我們通常查詢檔案使用windows自帶的查詢功能就能實現,但如果想要查詢指定資料夾內所有檔案包含的文字內容就需要使用專業一點的方法,這裡來舉出一些我常用的方法。比如,現在想在下載好的OpenWrt原始碼中找出包含"hg255d"關鍵字的文字內容。
        在windows平臺下,可以使用File Locator pro工具進行查詢:

        在linux平臺下,可以使用下面的命令進行查詢:
        find . -name "*" |xargs grep -sin "hg255d"

----------------------------------

SDK下載地址:   https://github.com/aggresss/RFDemo