OpenWrt的學習和總結

OpenWrt的學習和總結

https://blog.csdn.net/wdsfup/article/details/50687342

2016年02月18日 17:03:20 wdsfup 閱讀數:3211

OpenWrt的學習和總結

內容目錄

1OpenWrt背景知識 2

2OpenWrt 基礎知識 2

2.1目錄結構 2

2.2擴展軟件包feeds 3

2.3OpenWrt SDK 4

2.4固件升級 8

3OpenWrt內部機制 8

3.1UCI(unifiedconfiguration Interface) 8

3.2ubus 11

4LuCI 15

5參考 15

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  1. 1OpenWrt背景知識

Linksys成立於1988年,2003年被思科收購,最著名的產品爲WRT54G,爲降低成本Linksys決定使用基於Linux操作系統的固件,由於版權原因,釋放WRT54G/GS的源碼,網上出現了很多不同版本的Firmware。流行的第三方路由固件,主要DDWrt,Tomato,OpenWrt三個。

DDWRT:界面美觀,設置簡單直觀,易用性比較好,官方固件自帶的功能是三大固件中最爲豐富的,對新路由的支持也十分迅速,可支持迅速的同時,由於新代碼的加入,導致DDWRT經常出現一些Bug,一些可能之前已經解決的Bug,往往又會在之後的某次更新中原地滿狀態復活,着實讓人噴血,最讓人嘔病的,是孱弱的QOS功能,DDWRT的QOS功能只能說聊勝於無吧。

Tomato:界面尚可,設置也算簡單,易用性還行,流量的統計查看等功能是三個固件中做的最好的.官版Tomato是所有第三方路由固件中最爲穩定的,它的穩定源自於它的保守,官方版本的Tomato好幾個版本之前就已經沒有再加入什麼新功能,基本是對原有軟件的升級和除Bug,讓本來就穩定無比的Tomato更加穩定,可惜成也蕭何敗也蕭何,Tomato的聲譽來自於它的穩定,源自它的保守,它的缺點也來自於它的保守,由於這三大固件都源於思科當初開放的路由源碼,所以對思科以及和思科一樣採用BCM的54M芯片的機子的支持程度是最好的。

Openwrt:從零開始,一點一點的把各軟件加入進去,使其接近Linksys版Firmware的功能。是三大固件中擴展性最好的固件,通過擴展,可以實現很多超過路由本職工作的事情,比如脫機下載,網站,論壇,QOS功能也十分強大,不遜色於Tomato的QOS,設置得當後網絡表現會讓人偷着樂,而且OpenWrt對新路由的支持也是十分迅速,被認爲是最有前途的固件,因爲可以在新路由強勁CPU的支持下獲得很好的性能表現,各種功能的軟件擴展包比比皆是。

OpenWrt可以被描述爲一個嵌入式的Linux發行版,而不是試圖建立一個單一的、靜態的系統。OpenWrt的包管理提供了一個完全可寫的文件系統。對於開發人員,OpenWrt是使用框架來構建應用程序,而無需建立一個完整的固件來支持;對於用戶來說,這意味着其擁有完全定製的能力,可以用前所未有的方式使用該設備。

  1. 2OpenWrt 基礎知識

關於Openwrt的源代碼下載,途徑有二,一是通過svn,一是通過git,建議使用svn,因爲Openwrt主要以svn來維護Openwrt系統的版本。另外,請注意Openwrt中不同的分支版本,一個是用得較多的開發快照,俗稱trunk,二是穩定版,俗稱backfire。

  1. 2.1目錄結構

 

 

有幾個重要目錄:package,target, build_dir, staging_dir, bin, dl

上圖是openwrt的基本的目錄結構,其中白色部分是直接下載源碼就有的源目錄,藍色部分則是通過make之後產生的目錄。

 

tool和toolchain:是編譯固件image,獲取內核頭文件,二進制編譯器和調試器,c庫文件,需要用到的通用工具。

include:存放*.mk文件,這裏的文件是在Makefile裏被include的

scripts:對openwrt的包進行管理的perl腳本,存放各類腳本的目錄。比如:feeds腳本

target:裏面是各個平臺(arch)的相關代碼

package:裏面包含了我們在配置文件裏設定的所有編譯好的軟件包。默認情況下,會有默認選擇的軟件包。

bin:用來存放生成的ipk包,固件。

build_dir:目錄編譯時的臨時目錄,進行包的解壓,編譯和打補丁等。

staging_dir:是工具鏈的安裝位置

dl:是'download'的縮寫,在編譯前期,需要從網絡下載的數據包都會放在這個目錄下,這些軟件包的一個特點就是,會自動安裝在所編譯的固件中,也就是我們makemenuconfig的時候,爲固件配置的一些軟件包。如果我們需要更改這些源碼包,只需要將更改好的源碼包打包成相同的名字放在這個目錄下,然後開始編譯即可。編譯時,會將軟件包解壓到build_dir目錄下。

feeds:是通過命令./scripts/feedsupdate -a; ./scripts/feeds install-a之後安裝的擴展包目錄,這個目錄將所有的文件鏈接到package/feeds/中去了,裏面存放的就是按照feeds.conf.default文件中列舉的要處理的文件,所展開得到的目錄。目錄中存放的東西,和package目錄中大致相似,指導如何下載和編譯對應模塊的。

 

    1. 2.2擴展軟件包feeds

 

如果缺少一些應用程序可以是用feeds管理工具來安裝,feeds即爲包含到你的OpenWrt環境中的額外軟件包,有一個用perl寫的腳本(feeds)放在scripts目錄下,會根據feeds.config.default文件來進行相關的操作,feeds命令有:

 

 

./scripts/feedsupdate

./scripts/feedslist

./scripts/feedsinstall

./scripts/feedsuninstall

./scripts/feedssearch

./scripts/feessclean

 

在feed.config.default文件中有:

src-gitpackages https://github.com/openwrt/packages.git;for-15.05

src-gitluci https://github.com/openwrt/luci.git;for-15.05

src-linkluci ../qca/feeds/luci

src-svnxwrt http://x-wrt.googlecode.com/svn/trunk/package

 

src-svnphone svn://svn.openwrt.org/openwrt/feeds/phone

.....

.....

 

一般情況,你至少需要含packagesfeeds,其他可根據需求下載、安裝feeds。

*packages 提供衆多庫、工具等基本功能;也是其他feed所依賴的軟件源,因此在安裝其他feed前一定要先安裝packages!

*luci OpenWrt默認的GUI(WEB管理界面)

 

比如先安裝luci先要安裝packages包:

$./scripts/feeds install -p packages -a

$./scripts/feeds install -p luci -a

 

舉例:

下載、更新完feeds:

$./scripts/feeds update -a

 

要安裝feeds.conf中定義的全部feed,

$./scripts/feeds install -a

 

安裝某個feed的全部,

$./scripts/feeds install -p luci -a

 

搜索安裝所需的軟件包,這時候可以搜索安裝相關的軟件包,例如安裝和藍牙有關的軟件包:

$./scripts/feeds search bluetooth

Searchresults in feed 'packages':

anyremote A bluetooth remote control app

bemusedlinuxserver Bemused linux server

bluez-hcidump Bluetooth packet analyzer

bluez-libs Bluetooth library

bluez-utils Bluetooth utilities

miax A console iax (asterisk) client

python-bluez Python wrapper for the BlueZ Bluetooth stack

 

比如需要安裝bluez-libs和bluez-utils這兩個包,可以直接安裝他們:

$./scripts/feeds install bluez-libs bluez-utils

Collectingpackage info: done

Collectingtarget info: done

Installingpackage 'bluez-libs'

Installingpackage 'gettext'

Installingpackage 'libiconv'

Installingpackage 'bluez-utils'

Installingpackage 'dbus'

Installingpackage 'expat'

Installingpackage 'gettext-full'

Installingpackage 'libiconv-full'

feeds已經相當智能了,能夠根據軟件包間的依賴關係,自動把所依賴的軟件包也一同安裝了

 

    1. 2.3OpenWrt SDK

如果要編譯應用程序可以在OpenWrt源碼目錄下,也可以使用OpenWrtSDK。在makemenuconfig 是選擇 [*]Build the OpenWrtSDK,在bin目錄下生成,OpenWrt-SDK-ar71xx-xxxxx-0.9.33.2.tar.bz2包,目錄結構與OpenWrt結構基本相同,應用程序在SDK下編譯就可以,裏面有需要的所有依賴庫和交叉編譯工具。

 

新建一個helloworldproject舉例:

OpenWrt-SDK/package$mkdir helloworld

OpenWrt-SDK/package/helloworld$ls

Makefile src

OpenWrt-SDK/package/helloworld$ls src

helloworld.c Makefile

橙色的Makefile爲OpenWrt的Makefile,下面是模板:

##############################################

 

#OpenWrt Makefile for helloworld program

 

#

 

#

 

#Most of the variables used here are defined in

 

#the include directives below. We just need to

 

#specify a basic description of the package,

 

#where to build our program, where to find

 

#the source files, and where to install the

 

#compiled program on the router.

 

#

 

#Be very careful of spacing in this file.

 

#Indents should be tabs, not spaces, and

 

#there should be no trailing whitespace in

 

#lines that are not commented.

 

#

 

##############################################

 

include$(TOPDIR)/rules.mk

 

#Name and release number of this package

 

PKG_NAME:=helloworld

 

PKG_RELEASE:=1

 

 

 

 

 

#This specifies the directory where we're going to build the program.

 

#The root build directory, $(BUILD_DIR), is by default thebuild_mipsel

 

#directory in your OpenWrt SDK directory

 

PKG_BUILD_DIR:= $(BUILD_DIR)/$(PKG_NAME)

 

 

 

 

 

include$(INCLUDE_DIR)/package.mk

 

 

#Specify package information for this program.

 

#The variables defined here should be self explanatory.

 

#If you are running Kamikaze, delete the DESCRIPTION

 

#variable below and uncomment the Kamikaze define

 

#directive for the description below

 

definePackage/helloworld

 

SECTION:=utils

 

CATEGORY:=Utilities

 

TITLE:=Helloworld-- prints a snarky message

 

endef

 

 

 

#Uncomment portion below for Kamikaze and delete DESCRIPTION variableabove

 

definePackage/helloworld/description

 

Ifyou can't figure out what this program does, you're probably

 

brain-deadand need immediate medical attention.

 

endef

 

 

#Specify what needs to be done to prepare for building the package.

 

#In our case, we need to copy the source files to the build directory.

 

#This is NOT the default. The default uses the PKG_SOURCE_URL and the

 

#PKG_SOURCE which is not defined here to download the source from theweb.

 

#In order to just build a simple program that we have just written, itis

 

#much easier to do it this way.

 

defineBuild/Prepare

 

mkdir-p $(PKG_BUILD_DIR)

 

$(CP)./src/* $(PKG_BUILD_DIR)/

 

endef

 

 

 

 

 

#We do not need to define Build/Configure or Build/Compile directives

 

#The defaults are appropriate for compiling a simple program such asthis one

 

 

 

 

 

#Specify where and how to install the program. Since we only have onefile,

 

#the helloworld executable, install it by copying it to the /bindirectory on

 

#the router. The $(1) variable represents the root directory on therouter running

 

#OpenWrt. The $(INSTALL_DIR) variable contains a command to preparethe install

 

#directory if it does not already exist. Likewise $(INSTALL_BIN)contains the

 

#command to copy the binary file from its current location (in ourcase the build

 

#directory) to the install directory.

 

definePackage/helloworld/install

 

$(INSTALL_DIR)$(1)/bin

 

$(INSTALL_BIN)$(PKG_BUILD_DIR)/helloworld $(1)/bin/

 

endef

 

 

 

 

 

#This line executes the necessary commands to compile our program.

 

#The above define directives specify all the information needed, butthis

 

#line calls BuildPackage which in turn actually uses this informationto

 

#build a package.

 

$(eval$(call BuildPackage,helloworld))

 

 

 

src目錄下的Makefile爲:

 

#build helloworld executable when user executes "make"

 

helloworld:helloworld.o

 

$(CC)$(LDFLAGS) helloworld.o -o helloworld

 

helloworld.o:helloworld.c

 

$(CC)$(CFLAGS) -c helloworld.c

 

#remove object files and executable when user executes "makeclean"

 

clean:

 

rm*.o helloworld

 

 

編譯命令爲:

OpenWrt-SDK$makeV=99 package/helloworld/compile

成功後會在bin目錄下生成helloworld_1_ar71xx.ipk,在板子上是用opkg命令安裝。

opkginstall helloworld_1_ar71xx.ipk 就可以安裝到板子上。

 

Opkg是一個輕量快速的套件管理系統,目前已成爲Opensource界嵌入式系統標準。常用於路由、交換機等嵌入式設備中,用來管理軟件包的安裝升級與下載。

 

常用命令

opkgupdate 更新可以獲取的軟件包列表

opkgupgrade 對已經安裝的軟件包升級

opkglist 獲取軟件列表

opkginstall 安裝指定的軟件包

opkgremove 卸載已經安裝的指定的軟件包

 

    1. 2.4固件升級

Thegeneric Flash layout is:

 

Layer0

rawflash

Layer1

bootloader
partition(s)

optional
SoC
specific
partition(s)

OpenWrtfirmware partition

optional
SoC
specific
partition(s)

Layer2

LinuxKernel

rootfs
mounted:"/",OverlayFSwith/overlay

Layer3

/dev/root
mounted: "/rom",SquashFS
sizedepends on selected packages

rootfs_data
mounted:"/overlay",JFFS2
"free"space

             

 

/overlay/rom共同構成統一的/根目錄,rootfs_data使用overlayFS,可讀寫。

源碼編譯後會在bin目錄下生成固件包,對應上圖Layer1中的”OpenWrtfirmware partition“

openwrt-ar71xx-generic-ap152-16M-squashfs-sysupgrade.bin

三種方式:網頁升級,uboot,進入系統使用sysupgrade命令。

  1. 3OpenWrt內部機制
    1. 3.1UCI(unifiedconfiguration Interface)

Linux下的各種軟件包有不同的配置腳本,每個腳本的語法格式和操作方式不同,這樣的設計雖然體現了各個軟件自身的優勢,但同時也增加了學習難度,所以OpenWrt引入了一套配置參數管理系統,就是UCI(unifiedconfiguration Interface),意在OpenWrt整個系統的配置集中化。

UCI是一個用C語言編寫的小應用程序(也可用作一個shell腳本封裝器),其開發目的是集中管理一個OpenWrt設備內的所有配置選項。UCI是對OpenWrt歷史版本WhiteRussian上NVRAM基礎配置管理系統的一個繼承,是一個對衆多應用程序自帶的標準配置文件的包裝,比如像:/etc/network/interfaces,/etc/exports,/etc/dnsmasq.conf,/etc/samba/samba.conf等。你可以用任意文本編輯器或命令行應用程序uci來修改它們,也可通過各種編程API(如Shell,Lua和C)來修改它們,配置位置放在/etc/config下。如果要開機讀取/etc/config下面的配置文件進行相應的設置,需要在/etc/init.d下面增加啓動腳本。

 

UCI命令行工具:

uci:invalid option -- h

 

Usage:uci [<options>] <command> [<arguments>]

 

 

 

Commands:

 

batch

 

export [<config>]

 

import [<config>]

 

changes [<config>]

 

commit [<config>]

 

add <config> <section-type>

 

add_list <config>.<section>.<option>=<string>

 

del_list <config>.<section>.<option>=<string>

 

show [<config>[.<section>[.<option>]]]

 

get <config>.<section>[.<option>]

 

set <config>.<section>[.<option>]=<value>

 

delete <config>[.<section>[[.<option>][=<id>]]]

 

rename <config>.<section>[.<option>]=<name>

 

revert <config>[.<section>[.<option>]]

 

reorder <config>.<section>=<position>

 

 

UCI的依賴項

libuci一個用C語言寫的UCI的小程序庫

libuci-lua 一個Lua語言的插件,可被像LuCI的程序使用.

 

舉例子:/etc/config/network

 

root@OpenWrt:/#cat /etc/config/network

 

 

 

configinterface 'loopback'

 

optionifname 'lo'

 

optionproto 'static'

 

optionipaddr '127.0.0.1'

 

optionnetmask '255.0.0.0'

 

 

 

configglobals 'globals'

 

optionula_prefix 'auto'

 

 

 

configinterface 'wan0'

 

optionifname 'eth1'

 

optionproto 'dhcp'

 

 

 

configinterface 'lan0'

 

optionifname 'eth0_1 eth0_2 eth0_3 eth0_4'

 

optiontype 'bridge'

 

 

 

configinterface 'lan0_zone0'

 

optionifname 'br-lan0'

 

optionproto 'static'

 

optionipaddr '192.168.1.1'

 

optionnetmask '255.255.255.0'

 

 

root@OpenWrt:/#uci show network

 

network.loopback=interface

 

network.loopback.ifname='lo'

 

network.loopback.proto='static'

 

network.loopback.ipaddr='127.0.0.1'

 

network.loopback.netmask='255.0.0.0'

 

network.globals=globals

 

network.globals.ula_prefix='auto'

 

network.wan0=interface

 

network.wan0.ifname='eth1'

 

network.wan0.proto='dhcp'

 

network.lan0=interface

 

network.lan0.ifname='eth0_1eth0_2 eth0_3 eth0_4'

 

network.lan0.type='bridge'

 

network.lan0_zone0=interface

 

network.lan0_zone0.ifname='br-lan0'

 

network.lan0_zone0.proto='static'

 

network.lan0_zone0.ipaddr='192.168.1.1'

 

network.lan0_zone0.netmask='255.255.255.0'

 

 

api函數:

uci_lookup_ptr()

uci_foreach_element()

uci_to_section()

uci_lookup_option_string()

uci_set()

uci_commit()

...

...

 

 

如果你想在OpenWrt之外使用libuci(例如:您正在計算機上用C語言開發一個應用程序),下載源碼生成庫,編譯連接

$(CC)test.o -o test -luci

 

注意:所有的uciset,uci add,uci rename和ucidelete命令都是在/tmp中實現,並用ucicommit命令立即寫入flash.

 

    1. 3.2ubus

ubus是爲了OpenWrt中守護進程和應用程序之間通訊開發的,類似桌面的DBus,設計理念上與DBus基本保持一致,區別是簡化的API和簡練的模型,以適應embeddedrouter的特殊環境。與DBus一樣也是使用socket實現。

核心部分是ubusd守護進程,它提供了其他守護進程將自己註冊以及發送消息的接口。因爲這個,接口通過使用Unixsocket來實現,並使用TLV(type-length-value)消息,ubus內部使用Blob_buf,Blob_attr等結構來表示。

ubus有兩種調用,一個是method調用,一個是notification,其中method包括等待函數返回和不用等待返回,notification是廣播和DBus的signal類似。ubus使用是先建立連接,然後把連接加入epollset中。下面是它的一些調用API。

uloop_init(); 創建epoll句柄,最多監聽32個fd

ubus_connect(); 創建ubus連接

ubus_add_uloop(); 把創建的ubus連接註冊到epoll中。

ubus_add_object(); 註冊對象到的ubus連接。

uloop_run(); 等待I/O事件發生,調用相對應的對象的功能函數。

ubus_free(); 關閉ubus連接

uloop_done(); 關閉epoll句柄

 

ubus調試有一個命令行工具叫ubus,ubus可以和ubusd服務器交互(和當前所有已經註冊的服務).它對研究和調試註冊的命名空間以及編寫腳本非常有用。可以調用帶參數和返回信息的方法,它使用友好的JSON格式。JSON(JavaScriptObjects Notation)是一種輕量級的數據交換方式,JSON是humannice type,有兩種數據結構對象和數組。

對象: {“firstname”:“Brett”,“lastname”:“Mical”}

數組:[“aaa”,“bbb”, “ccc”]

 

下面是它的命令說明。

ubus Commands:

 

-list [<path>] List objects

 

-call <path> <method> [<message>] Call an objectmethod

 

-listen [<path>...] Listen for events

 

-send <type> [<message>] Send an event

 

-wait_for <object> [<object>...] Wait for multipleobjects to appear on

 

ubuslist缺省列出所有向服務器註冊的命名空間,如果調用時包含參數-v,將會顯示指定命名空間更多方法參數等信息。

ubuscall 調用指定命名空間中指定的方法,並且通過消息傳遞給它,消息參數必須是有效的JSON字符串,並且攜帶函數所要求的鍵及值。

Ubuslisten 設置一個監聽socket並觀察進入的事件。

Ubussend 發送一個事件提醒。

root@uplink:~#ubus listen &

 

舉例:

server.c

structblobmsg_policy discovery_pair_device_policy[] = {

[0]= { .name = "mac", .type = BLOBMSG_TYPE_STRING },

};

intdiscovery_pair_device_policy_sz = ARRAY_SIZE(discovery_pair_device_policy );

staticstruct ubus_method discovery_methods[] = {

UBUS_METHOD_NOARG("broadcast", discovery_broadcast ),

UBUS_METHOD_NOARG("get_devices", discovery_get_devices ),

UBUS_METHOD("pair_device", discovery_pair_device,discovery_pair_device_policy ),

UBUS_METHOD_NOARG("get_paired_devices", discovery_get_paired_devices ),

UBUS_METHOD("get_pairing_status", discovery_get_pairing_status,discovery_get_pairing_status_policy ),

};

staticstruct ubus_object_type discovery_object_type = UBUS_OBJECT_TYPE("controller.discovery", discovery_methods );

 

staticstruct ubus_object discovery_object = {

.name= "controller.discovery",

.type= &discovery_object_type,

.methods= discovery_methods,

.n_methods= ARRAY_SIZE( discovery_methods ),

};

 

int main( int argc, char** argv)

{

structubus_context* ubus_context;

intret;

uloop_init();

ubus_context= ubus_connect( NULL );

if( !ubus_context )

{

fprintf(stderr, "Failed to connect to ubus\n" );

gotoout;

}

ubus_add_uloop(ubus_context );

ret= ubus_add_object( ubus_context, &discovery_object );

if( ret ) {

pr_debug("Failed to add discovery object: %s\n", ubus_strerror( ret) );

}

uloop_run();

 

ubus_free(ubus_context );

uloop_done();

 

out:

return0;

}

//=============================================================================

int

discovery_pair_device(

structubus_context* ubus_context,

structubus_object* obj,

structubus_request_data* req,

constchar* method,

structblob_attr* msg

)

//=============================================================================

{

structdevice_descriptor* node;

structblob_attr* args[1];

intstatus = 0;

charmac[AP_ID_LEN + 1];

 

blobmsg_parse(

discovery_pair_device_policy,

discovery_pair_device_policy_sz,

args,

blob_data(msg ),

blob_len(msg ) );

 

if( args[0] ) {

memset(mac, 0, sizeof ( mac ) );

strncpy(mac, blobmsg_data( args[0] ), sizeof ( mac ) - 1 );

}

else

gotoerror;

 

//dosomething and set status

 

blob_buf_init(&reply, 0 );

blobmsg_add_u32(&reply, "status", status );

ubus_send_reply(ubus_context, req, reply.head );

 

returnUBUS_STATUS_OK;

}

 

client程序

staticstruct ubus_context *ctx;

staticstruct blob_buf b;

int main(int argc, char **argv)

//=============================================================================

{

constchar *progname;

intoption_index;

intc;

charbuf[80];

 

progname= argv[0];

uint32_tid;

ubus_ctx= ubus_connect( NULL );

if(!ubus_ctx ) {

fprintf(stderr, "Couldn't connect to UBUS.\n");

return0;

}

if(ubus_lookup_id( ubus_ctx, "controller.discovery", &id )) {

fprintf(stderr, "Couldn't find controller.discovery.\n");

return0;

}

 

blob_buf_init(&b, 0 );

if( argc == 1 ) return print_usage( progname );

while( (c = getopt_long( argc, argv, "hdlp:s:", long_options,&option_index)) != -1 ) {

switch( c ) {

case'd':

ubus_invoke( ubus_ctx, id, "broadcast", b.head,print_json, NULL, 1000 );

return 1;

case'p':

sprintf( buf, "{ \"mac\" : \"%s\" }",optarg );

blobmsg_add_json_from_string( &b, string_tolower(buf) );

ubus_invoke( ubus_ctx, id, "pair_device", b.head,print_json, NULL, 1000 );

return 1;

default:

return print_usage( progname );

}

}

return0;

}

 

ubus命令執行:

root@OpenWrt:/#ubus list controller.discovery -v

 

'controller.discovery'@1cabe8bf

 

"broadcast":{}

 

"get_devices":{}

 

"pair_device":{"mac":"String"}

 

"get_paired_devices":{}

 

"get_pairing_status":{"mac":"String"}

 

 

root@OpenWrt:/#ubus call controller.discovery pair_device '{"mac":"00010203040

 

506"}'

 

{

 

"status":"(error)"

 

}

 

 

 

notification函數有:

ubus_notify();

ubus_notify_async();

ubus_register_subscriber();

ubus_subscribe()

ubus_unsubscribe();

  1. 4LuCI

OpenWrt利用uhttpd作爲web服務器,OpenWrt使用LuCI實現客戶端web頁面配置功能。LuCI採用了MVC(模型-視圖-控制)三層架構,同時其使用Lua腳本,在/usr/lib/lua/luci下面對應有model,view和controller目錄。開發LuCI的配置界面一般不需要編輯任何的Html代碼,除非想自己單獨去創建網頁(View層)。

資源目錄放在/www目錄下面,index.html指向了目錄下的cgi-bin/luci。對於request處理方式,採用的是cgi,而所用的cgi程序就是luci。調用工作框架如下圖所示:

 

 

 

 

 

 

 

 

 

 

Client端和server端採用cgi方式交互,uhttpd服務器的cgi方式中,fork出一個子進程,子進程利用execl替換爲luci進程空間,並通過setenv環境變量的方式,傳遞一些固定格式的數據(如PATH_INFO)給luci。另外一些非固定格式的數據(post-data)則由父進程通過一個w_pipe寫給luci的stdin,而luci的返回數據則寫在stdout上,由父進程通過一個r_pipe讀取。

LuCI的配置文件默認放在/etc/config目錄下,如ip網關,等信息,可以使用UCI(unifiedconfiguration Interface)對文件進行讀寫,有命令和api接口兩種方式,但修改,刪除操作後需要執行ucicommit,否則不會保存到文件中。

 

LuCI的安裝兩種方式:

 

a.使用OpenWrt源:

*轉到OpenWrt根目錄,編輯feed.config.default打開luci源。

*輸入./scripts/feedsupdate

*輸入./scripts/feedsinstall -a -p luci

*輸入makemenuconfig

*在”LuCI”菜單下你將找到所有的組件。

*make V=99

 

b.使用OpenWrt安裝包版本庫:

*添加一行文字到你的/etc/opkg.conf中,即將LuCI添加到版本庫中:

srclucihttp://downloads.openwrt/kamikaze/8.09.2/YOUR_ARCHITECTURE/packages

*輸入opkg update

*LuCI簡版,輸入:opkg install luci-light

LuCI普通版:opkg install luci

 

  1. 5參考

https://wiki.openwrt.org/doc/techref/start

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章