图2 SQLite 的内部结构
SQLite 的接口是一些已经编写好的C库,即使使用不同语言的API,在底层仍然使用C 库执行。SQL语句通过接口进入到高效的SQL编译器,由标记处理器( tokeni2zer)分解成柠檬分析器(par ser) 可以识别的各个标志符,然后由分析器重新组合标志符并调用代码生成器(code generator) 生成虚拟机器码,交由虚拟机( virtual machine)去执行,最终完成SQL 语句指定的任务。虚拟机是SQLite 内部结构的核心,不仅完成与数据操作相关的全部操作,而且还是客户和存储之间信息进行交换的中间单元。数据库按照B树(B2t ree) 的形式存储在磁盘上,通过可调整的页面缓冲(pager) 获得对数据的快速查找和存储。为了方便移植,SQLite 使用一个抽象层接口(OS in2terface) 与不同操作系统进行对接。
4.2. 2 SQLite 开发技术
SQLite 本身提供了C 语言的API 接口,使得对数据库的操作十分简单,主要是对3个API 函数的调用。 (1) 打开数据库 int sqlite3 open (
const char 3 filename , / 3 数据库文件名(U TF28) 3 / sqlite3 3 3 ppDb / 3 输出SQLite 数据库句柄3 / ) ;
(2) 执行SQL
27
int sqlite3 exec (
sqlite3 3 , / 3 已经打开的数据库句柄3 / const char 3 sql , / 3 要执行的SQL 语句3 / sqlite callback , / 3 回调函数3 /
void 3 , / 3 回调函数的第一个参数3 / char 3 3 errmsg / 3 错误信息返回3 / ) ;
(3) 关闭数据库
int sqlite3 close ( sqlite3 3 ) ; / 3 参数就是打开时的结构体,即数据库句柄3 /
其中,sglite3 exec ( ) 函数的第二个参数用来处理一条或多条SQL 语句,语句间必须用“;”号隔开。如果是查询(SEL ECT) 语句,查询结果的每一条记录都必须调用第三个参数的Callback 函数,第四个参数则为Callback 函数的第一个参数指针。如果不是查询语句,第三、四个参数为NULL。所有SQL 执行完毕后返回0,否则返回错误代码,可通过第五个参数值来查看详细错误信息。
4.3 SQLite 在ARM-Linux 平台上的实现
SQLite 嵌入式数据库提供了以源码发布的方式,要在众多的硬件平台进行移植,可以根据不同平台对源码进行交叉编译来实现。编译主要有以下几个步骤: ① 到http :/ / www. sqlite. org/ 的cvs中下载最新的源代码包,解压并根据需要进行适当的修改后将生成sqlite目录,另外新建并转到一个与sqlite目录平行的同级目录,如make目录。
②用“echo $PATH”命令查看PATH中是否已经包含交叉编译工具arm linux gcc。 ③为了在ARM Linux下能正常运行sqlite,需要对sqlite/ src/ sqliteInt . h作一定的修改,以确保bt ree (B 树)有正确的变量大小,如“pt r”和“char 3 ”。不同体系结构的Linux,如x86 和ARM,会有些差别。对于ARM2Linux可以找到如下部分: # ifndef IN TPTR_ TYPE # if SQL ITE_PTR_SZ = = 4
28
# 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”类型,而不是“long long”。
④准备使用configure进行一些配置。请在sqlite目录下的configure中找到如下4处,并将他们注释掉,这样可以让configure不去检查你的交叉编译环境。 ⑤修改Makefile文件。将代码行BCC = arm linux gcc g O2 改成BCC = gcc g O2 。另外,一般是以静态链接的形式将sqlite 放到ARM Linux 的硬件板上运行的,所以继续修改Makefile ,找到标记为sqlite :的代码段,将其中的libsqlite. la 改成. libs/ libsqlite. a 。做完上述修改,用make 生成sqlite 、libsqlite. a 、libsqlite. so 。为了减小执行文件大小可以用st rip 处理,去掉其中的调试信息。
⑥在ARM 板上运行sqlite。将sqlite 拷贝到ARM板上,方法很多,需要根据具体的情况来选择。如ftp 、cm2 dftp 、wget 等。将sqlite下载到ARM 板的/ tmp 目录,因为此目录是可写的。修改权限并运行: chmod + wx sqlite . / sqlite test . sqlite 会出现 sqlite >
如果一切正常,现在sqlite已经在ARM Linux下跑了起来,然后就可以基于此进行进一步的应用开发了。
4.4 SQLite 在ARM- Linux 系统中应用实例
在基于Linux的媒体网络附属存储(media network attached storage,Media NAS)系统中,选用SQLite数据库作为NAS系统中媒体数据的存储数据库,使得数字
29
媒体播放设备通过UPnP ( universal plug-and-play)协议对NAS上的媒体文件进行播放。该系统中用户浏览媒体文件的流程如下::
(1)当用户浏览NAS系统中的媒体文件时,执行DatabaseOpen数据库打开操作。 (2)接着查找当前的SQLite数据库表,得到媒体文件的路径,通过DatabaseExecute执行SQL 查询语句得到路径。
(3)通过媒体文件的路径打开媒体文件,把媒体文件,通过UPnP网络发送出去。SQLite的特点决定了它与应用结合时的便捷性。作为数据的存储介质,SQLite文件被保存为一个普通的磁盘二进制文件,它无需一个服务器进程来提供服务,对SQLite数据文件的直接操作即可完成想要做的工作。结合应用需求,在应用层编写了一组对SQLite的API调用操作的简单封装,部分封装函数如下:: DatabaseOpen ;调用SQLite_open打开数据库文件
DatabaseClose ;调用SQLite_close关闭数据库
DatabaseExecute ;执行SQL命令 应用层的部分封装函数的实现代码如下::
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 ( \ return 1;
30
}
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; }
可以看出,各个封装函数是通过调用SQLite的API函数实现的。在基于Linux操作系统上使用SQLite,经测试嵌入式数据库响应迅速,运行稳定,用户基本感觉不到命令延迟,在浏览声音和图像媒体时流畅自然,充分验证了使用SQLite数据库的优越性。
总结
在经过大量的分析对比之后,针对嵌入式系统开发的特点,从众多数据库发行版中选出非常适用的嵌入式数据库SQLite。ARM-Linux下完成了对SQLite的编译,并基于此在项目中作了进一步的开发工作。实践证明,SQLite能够出色地完成嵌入式系统中的数据库应用需求。
31
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库基于ARM的程序移植 - 图文(7)在线全文阅读。
相关推荐: