基于A(yíng)RM-Linux的SQLite嵌入式數據庫的研究
關(guān)鍵詞:嵌入式數據庫;SQLite;ARM-Linux平臺;交叉編譯
Abstract :SQLite is an open source embedded SQL database engine. At first,descripe some general databases’ technology in this paper, and then Internal architecture and developing method of SQLite are analyzed. The application developing ,cross compiling and porting in ARM-Linux platform are also introduced and a detailed example is given for presentation.
Keywords :Embedded Databese; SQLite; ARM-Linux platform; cross compiling
引言
隨著(zhù)嵌入式系統的廣泛應用和用戶(hù)對數據處理和管理需求的不斷提高,各種智能設備和數據庫技術(shù)的緊密結合已經(jīng)得到了各方面的重視。不久的將來(lái)嵌入式數據庫將無(wú)處不在??v觀(guān)目前國際、國內嵌入式數據庫的應用情況,目前基于嵌入式數據庫應用的市場(chǎng)已經(jīng)進(jìn)入加速發(fā)展的階段。
1 嵌入式數據庫
1.1 嵌入式數據庫的設計
嵌入式數據庫系統是指支持某種特定計算模式或移動(dòng)計算的數據庫管理系統,它通常與操作系統和具體應用集成在一起,運行在智能型嵌入式設備或移動(dòng)設備上。嵌入式數據庫的使用是采用程序驅動(dòng),即由程序調用相應的API來(lái)實(shí)現數據的存取。具有體積小巧、快速高效、穩定可靠、可移植性等特點(diǎn),非常適用于嵌入式環(huán)境下的數據管理.。
嵌入式數據庫的主要設計思想如下圖1所示,在向上層應用提供標準的數據庫接口的同時(shí),擺脫傳統數據庫僅僅由軟件驅動(dòng)的束縛,根據嵌入式系統的實(shí)際情況用SOC技術(shù)同時(shí)實(shí)現硬件驅動(dòng)。軟件部分按SQL92標準實(shí)現SQL語(yǔ)句的解析,實(shí)現事務(wù)管理功能、數據同步機制、數據的備份和恢復,軟件部分不關(guān)心數據的實(shí)際存儲,用標準C實(shí)現,能同任何嵌入式操作系統內核一同編譯,能支持各嵌入式操作系統的安裝格式,由數據庫硬件驅動(dòng)專(zhuān)用芯片實(shí)現對實(shí)際數據的訪(fǎng)問(wèn)功能(存儲器讀寫(xiě),I/O通訊,異構數據庫接駁)。
圖1 嵌入式數據庫驅動(dòng)結構圖
1.2. 嵌入式數據庫SQLite
SQLite 是D. Richard Hipp 在2000年開(kāi)發(fā)的一個(gè)小型嵌入式數據庫。他是完全獨立的,不具有外部依賴(lài)性,可以較為方便地應用于嵌入式系統中。其源代碼完全開(kāi)放,可以免費用于任何用途,包括商業(yè)目的。SQLite 雖然是個(gè)極端輕量級的關(guān)系數據庫,卻保留了數據庫的大部分特征,他提供了對SQL92 標準的大多數支持:支持多表和索引、事務(wù)、視圖、觸發(fā)和一系列的用戶(hù)接口及驅動(dòng)。其主要特征如下::
(1) 支持原子的、一致的、獨立的和持久的(ACID) 事務(wù)特性,即使系統崩潰和掉電。
(2) 零配置(Zero2configuration),無(wú)需安裝和管理。
(3) 一個(gè)完整的數據庫存儲在單一磁盤(pán)文件中。
(4) 數據庫文件可以在不同字節順序的機器間自由共享。
(5) 支持數據庫大小至2 TB。
(6) 字符串和二進(jìn)制大對象(BLOBs) 的大小僅被有效內存限制。
(7) 源碼體積小,編譯后低于250 kB。
(8) 大部分的操作比關(guān)系型數據庫引擎要快。
(9) 簡(jiǎn)單易用的API。
SQLite 由于小、快、簡(jiǎn)單、可靠,而且作者完全放棄版權,從他一發(fā)布出來(lái),便深受歡迎。對于嵌人式環(huán)境,管理、執行、維護的簡(jiǎn)單化比企業(yè)數據庫引擎提供的許多復雜應用更重要,因此SQLite 數據庫是一個(gè)很好的選擇。
2 SQLite 內部結構及開(kāi)發(fā)技術(shù)
2. 1 SQLite 內部結構
SQLite 采用模塊化的設計,主要由4個(gè)部分組成:內核(Core)、SQL編譯器( SQL Compiler)、后端(Backend)以及附件(Accessories)。內部結構如圖2所示。
圖2 SQLite 的內部結構
SQLite 的接口是一些已經(jīng)編寫(xiě)好的C庫,即使使用不同語(yǔ)言的API,在底層仍然使用C 庫執行。SQL語(yǔ)句通過(guò)接口進(jìn)入到高效的SQL編譯器,由標記處理器( tokeni2zer)分解成檸檬分析器(par ser) 可以識別的各個(gè)標志符,然后由分析器重新組合標志符并調用代碼生成器(code generator) 生成虛擬機器碼,交由虛擬機( virtual machine)去執行,最終完成SQL 語(yǔ)句指定的任務(wù)。虛擬機是SQLite 內部結構的核心,不僅完成與數據操作相關(guān)的全部操作,而且還是客戶(hù)和存儲之間信息進(jìn)行交換的中間單元。數據庫按照B樹(shù)(B2t ree) 的形式存儲在磁盤(pán)上,通過(guò)可調整的頁(yè)面緩沖(pager) 獲得對數據的快速查找和存儲。為了方便移植,SQLite 使用一個(gè)抽象層接口(OS in2terface) 與不同操作系統進(jìn)行對接。
2. 2 SQLite 開(kāi)發(fā)技術(shù)
SQLite 本身提供了C 語(yǔ)言的API 接口,使得對數據庫的操作十分簡(jiǎn)單,主要是對3個(gè)API 函數的調用。
(1) 打開(kāi)數據庫
int sqlite3 open (
const char 3 filename , / 3 數據庫文件名(U TF28) 3 /
sqlite3 3 3 ppDb / 3 輸出SQLite 數據庫句柄3 /
) ;
(2) 執行SQL
int sqlite3 exec (
sqlite3 3 , / 3 已經(jīng)打開(kāi)的數據庫句柄3 /
const char 3 sql , / 3 要執行的SQL 語(yǔ)句3 /
sqlite callback , / 3 回調函數3 /
void 3 , / 3 回調函數的第一個(gè)參數3 /
char 3 3 errmsg / 3 錯誤信息返回3 /
) ;
(3) 關(guān)閉數據庫
int sqlite3 close ( sqlite3 3 ) ; / 3 參數就是打開(kāi)時(shí)的結構體,即數據庫句柄3 /
其中,sglite3 exec ( ) 函數的第二個(gè)參數用來(lái)處理一條或多條SQL 語(yǔ)句,語(yǔ)句間必須用“;”號隔開(kāi)。如果是查詢(xún)(SEL ECT) 語(yǔ)句,查詢(xún)結果的每一條記錄都必須調用第三個(gè)參數的Callback 函數,第四個(gè)參數則為Callback 函數的第一個(gè)參數指針。如果不是查詢(xún)語(yǔ)句,第三、四個(gè)參數為NULL。所有SQL 執行完畢后返回0,否則返回錯誤代碼,可通過(guò)第五個(gè)參數值來(lái)查看詳細錯誤信息。
3 SQLite 在ARM-Linux 平臺上的實(shí)現
SQLite 嵌入式數據庫提供了以源碼發(fā)布的方式,要在眾多的硬件平臺進(jìn)行移植,可以根據不同平臺對源碼進(jìn)行交叉編譯來(lái)實(shí)現。編譯主要有以下幾個(gè)步驟:
① 到http :/ / www. sqlite. org/ 的cvs中下載最新的源代碼包,解壓并根據需要進(jìn)行適當的修改后將生成sqlite目錄,另外新建并轉到一個(gè)與sqlite目錄平行的同級目錄,如make目錄。
②用“echo $PATH”命令查看PATH中是否已經(jīng)包含交叉編譯工具arm linux gcc。
③為了在A(yíng)RM Linux下能正常運行sqlite,需要對sqlite/ src/ sqliteInt . h作一定的修改,以確保bt ree (B 樹(shù))有正確的變量大小,如“pt r”和“char 3 ”。不同體系結構的Linux,如x86 和ARM,會(huì )有些差別。對于A(yíng)RM2Linux可以找到如下部分:
# ifndef IN TPTR_ TYPE
# if SQL ITE_PTR_SZ = = 4
# define IN TPTR_ TYPE int
# else
# define IN TPTR_ TYPE long long
# endif
在上面的代碼前加上一句
# define SQL ITE_PTR_SZ 4
這樣后面的“typedef INTPTR_ TYPE pt r ;”就是定義的“int”類(lèi)型,而不是“l(fā)ong long”。
④準備使用configure進(jìn)行一些配置。請在sqlite目錄下的configure中找到如下4處,并將他們注釋掉,這樣可以讓configure不去檢查你的交叉編譯環(huán)境。
⑤修改Makefile文件。將代碼行BCC = arm linux gcc g O2 改成BCC = gcc g O2 。另外,一般是以靜態(tài)鏈接的形式將sqlite 放到ARM Linux 的硬件板上運行的,所以繼續修改Makefile ,找到標記為sqlite :的代碼段,將其中的libsqlite. la 改成. libs/ libsqlite. a 。做完上述修改,用make 生成sqlite 、libsqlite. a 、libsqlite. so 。為了減小執行文件大小可以用st rip 處理,去掉其中的調試信息。
⑥在A(yíng)RM 板上運行sqlite。將sqlite 拷貝到ARM板上,方法很多,需要根據具體的情況來(lái)選擇。如ftp 、cm2 dftp 、wget 等。將sqlite下載到ARM 板的/ tmp 目錄,因為此目錄是可寫(xiě)的。修改權限并運行:
chmod + wx sqlite
. / sqlite test . sqlite
會(huì )出現
sqlite >
如果一切正常,現在sqlite已經(jīng)在A(yíng)RM Linux下跑了起來(lái),然后就可以基于此進(jìn)行進(jìn)一步的應用開(kāi)發(fā)了。
4 SQLite 在ARM- Linux 系統中應用實(shí)例
在基于Linux的媒體網(wǎng)絡(luò )附屬存儲(media network attached storage,Media NAS)系統中,選用SQLite數據庫作為NAS系統中媒體數據的存儲數據庫,使得數字媒體播放設備通過(guò)UPnP ( universal plug-and-play)協(xié)議對NAS上的媒體文件進(jìn)行播放。該系統中用戶(hù)瀏覽媒體文件的流程如下::
(1)當用戶(hù)瀏覽NAS系統中的媒體文件時(shí),執行DatabaseOpen數據庫打開(kāi)操作。
(2)接著(zhù)查找當前的SQLite數據庫表,得到媒體文件的路徑,通過(guò)DatabaseExecute執行SQL 查詢(xún)語(yǔ)句得到路徑。
(3)通過(guò)媒體文件的路徑打開(kāi)媒體文件,把媒體文件,通過(guò)UPnP網(wǎng)絡(luò )發(fā)送出去。SQLite的特點(diǎn)決定了它與應用結合時(shí)的便捷性。作為數據的存儲介質(zhì),SQLite文件被保存為一個(gè)普通的磁盤(pán)二進(jìn)制文件,它無(wú)需一個(gè)服務(wù)器進(jìn)程來(lái)提供服務(wù),對SQLite數據文件的直接操作即可完成想要做的工作。結合應用需求,在應用層編寫(xiě)了一組對SQLite的API調用操作的簡(jiǎn)單封裝,部分封裝函數如下::
DatabaseOpen ;調用SQLite_open打開(kāi)數據庫文件
DatabaseClose ;調用SQLite_close關(guān)閉數據庫
DatabaseExecute ;執行SQL命令
應用層的部分封裝函數的實(shí)現代碼如下::
int DatabaseOpen ( struct DBObj3 db, const char3 dbName)
{
char3 pzErrMsg = NULL;
structDB Info3 pDB info; / /數據庫文件指針
if (NULL = = dbName) return 1;
pDBinfo = ( struct DB Info3 ) db - > priv;
pDBinfo - > stConnect = ( struct sqlite3 ) sqlite_open ( dbName, 0777, pzErrMsg) ;
if ( NULL = = pDB info - > stConnect )
{
printf ( " db open error. " ) ;
return 1;
}
return 0;
}
int DatabaseExecute ( struct DBObj3 db, const char3 szSQL)
{
char3 pErrMsg = NULL;
int nErrorCode;
struct DB Info3 pDBinfo;
pDB info = ( structDB Info3 ) db ―> priv;
nErrorCode = sqlite_exec ( ( struct sqlite 3 )(pDBinfo - > stConnect) ,
szSQL, NULL, NULL, pErrMsg) ;
return nErrorCode;
}
可以看出,各個(gè)封裝函數是通過(guò)調用SQLite的API函數實(shí)現的。在基于Linux操作系統上使用SQLite,經(jīng)測試嵌入式數據庫響應迅速,運行穩定,用戶(hù)基本感覺(jué)不到命令延遲,在瀏覽聲音和圖像媒體時(shí)流暢自然,充分驗證了使用SQLite數據庫的優(yōu)越性。
5 總結
在經(jīng)過(guò)大量的分析對比之后,針對嵌入式系統開(kāi)發(fā)的特點(diǎn),從眾多數據庫發(fā)行版中選出非常適用的嵌入式數據庫SQLite。ARM-Linux下完成了對SQLite的編譯,并基于此在項目中作了進(jìn)一步的開(kāi)發(fā)工作。實(shí)踐證明,SQLite能夠出色地完成嵌入式系統中的數據庫應用需求。
參考文獻
[1] 譚愛(ài)國,琚長(cháng)江,余 濤.SQLite在基于L inux的Media NAS系統中的應用[J]。武漢理工大學(xué)學(xué)報:信息與管理工程版, 2007, 29 (6)
[2] 曾立勝. 基于SQL ite嵌入式數據庫的射頻卡數據存儲[ J ]. 電腦知識與技術(shù), 2006 (8)
[3] 倪天龍,張賢高,王培.數據庫SQLite在嵌入式系統中的應用[ J ]. 單片機與嵌入式系統應用, 2005 (10) : 35 - 37.
[4] 萬(wàn)瑪寧. 嵌入式數據庫典型技術(shù)SQLite和Berkeley DB的研究[J]. 微計算機信息,2006/02
[5] 王冠宇. JAVA在SQLite嵌入式數據庫中的應用[J]. 微計算機信息,2006/02
linux操作系統文章專(zhuān)題:linux操作系統詳解(linux不再難懂)
評論