嵌入式Linux 之 sqlite3 交叉编译和使用

简介: hello 大家好,今天给大家推荐一个小型的嵌入式数据库sqlite,介绍一下sqlite 交叉编译和使用。

1. 什么是sqlite?


sqlite 是一个小型,高速、高可靠性功能齐全的sql数据库引擎,并且是C语言开源的库,可以很方便的移植到各种嵌入式平台上。


官网如下:


image.png


地址:http://www3.sqlite.org/index.html


最新版本:3.3.52


2. sqlite 交叉编译


源码下载


image.png


tar -zxvf sqlite-autoconf-3350200.tar.gz


交叉编译


cd sqlite-autoconf-3350200
mkdir pc_out
./configure --prefix=~/work/github/sqlite-autoconf-3350200/pc_out
make 
make install


安装完成文件如下:


image.png


  • sqlite3:应用程序,直接可以打开和创建数据库


  • include:头文件,开发用


  • lib:sqlite3 的库,开发用


  • share:共享文件和手册


编译完成可以直接在pc上运行 sqlite3。


mips


mips 交叉编译和 pc 差不多,不过有一点不同,我们需要配置工具链:


准备工作:


cd sqlite-autoconf-3350200
mkdir mips_out
mkdir mips_out/glibc #创建glibc 目录
mkdir mips_out/uclibc#创建uclibc 目录
make distclean


编译glibc:


第一步:配置configure。设置工具链和安装路径


./configure --prefix=~/work/github/sqlite-autoconf-3350200/mips_out/glibc --host=mips-linux-gnu


  • --prefix:指定安装路径。


  • --host:指定工具链。注意,需要设置工具链的环境变量,否则检测不到工具链。


配置完成后,可以打开Makefile 验证:


image.png


第二步:编译和安装:


make 
make install


image.png


编译 uclibc:


第一步:配置configure。设置工具链和安装路径


# 需要手动修改Makefile CFLAGS += -muclibc
./configure --prefix=~/work/github/sqlite-autoconf-3350200/mips_out/uclibc --host=mips-linux-gnu
# 或者
CFLAGS += -muclibc ./configure --prefix=~/work/github/sqlite-autoconf-3350200/mips_out/uclibc --host=mips-linux-gnu


  • --prefix:指定安装路径。


  • --host:指定工具链。注意,需要设置工具链的环境变量,否则检测不到工具链。


  • CFLAGS += -muclibc:指定uclibc 环境



第二步:编译和安装


make 
make install


image.png


arm


arm 平台交叉编译类似。需要注意的点如下:


  • 设置工具链的环境变量


  • 指定交叉编译工具链为arm平台所用的工具链。比如 arm-linux-gnu(只要前缀)


3. sqlite 使用


当交叉编译后,就可以直接把sqlite3 拷贝到板子上运行。注意,glibc环境拷贝glibc的,uclibc环境拷贝uclibc的。


我们来看一个简单的示例:


#include <stdio.h>
#include <pthread.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <string.h>
#include <sqlite3.h>
#define DATABASE_NAME                 "MyDBDemo.db"
#define DATABASE_TABLE_NAME           "table1"
#define DATABASE_TABLE_MEMBER         "name text, age int, note text, count int"
#define DATABASE_TABLE_LABEL          "name, age, note, count"
#define CREATE                        0
#define INSERT                        1
#define DELETE                        2
#define SELECT                        3
#define UPDATE                        4
#define DROP                          5
#define VACUUM                        6
#define PRAGMA                        7
struct sqlite_db_str {
 char *sql;
};
struct sqlite_db_str db_sqlstr[] = {
 [CREATE] = { .sql = "CREATE TABLE " },
 [INSERT] = { .sql = "INSERT INTO "  },
 [DELETE] = { .sql = "DELETE FROM "  },
 [SELECT] = { .sql = "SELECT "  },
 [UPDATE] = { .sql = "UPDATE "  },
 [DROP] =   { .sql = "DROP TABLE "  },
 [VACUUM] = { .sql = "VACUUM "  },
 [PRAGMA] = { .sql = "PRAGMA "  },
};
int main(int argc, char *argv[])
{
 int ret = -1;
 int k = 0;
 sqlite3 *db_ctx = NULL;
 char *zErrMsg = NULL;
 /*Step1: create database */
 ret = sqlite3_open_v2(DATABASE_NAME, &db_ctx, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_SHAREDCACHE, NULL);
 if(ret){
  printf("Open %s database errror!, ret: %d\n", DATABASE_NAME, ret);
  return -1;
 }
 /*Step2: create table */
 char sql_buf[256] = {'\0'};
 sprintf(sql_buf, "%s %s (%s);", db_sqlstr[CREATE].sql, DATABASE_TABLE_NAME, DATABASE_TABLE_LABEL);
 ret = sqlite3_exec(db_ctx, sql_buf, NULL, NULL, &zErrMsg);
 if( ret != SQLITE_OK ){
  if( ret == 1 ){
   /* table already exists */
   printf("database [%s]: %s\n", DATABASE_NAME, zErrMsg);
  } else {
   fprintf(stderr, "SQL error: %s, ret: %d\n", zErrMsg, ret);
   sqlite3_free(zErrMsg);
   return -1;
  }
 }
 /*Step3: insert*/
 for (k = 0; k < 10; k++) {
  char insert_buf[128] = {0};
  sprintf(insert_buf, "'%s%d', %d, 'note_%d', %d", "Vinson", k, k, k, k);
  char sql_buf[1024] = {'\0'};
  unsigned int sql_prefix_len = 0;
  sprintf(sql_buf, "%s %s (%s) VALUES (", db_sqlstr[INSERT].sql, DATABASE_TABLE_NAME, DATABASE_TABLE_LABEL);
  sql_prefix_len = strlen(sql_buf);
  memcpy(sql_buf+sql_prefix_len, insert_buf, strlen(insert_buf));
  memcpy(sql_buf+sql_prefix_len + strlen(insert_buf), ");", strlen(");"));
  /* INSERT table1 (name age note count) VALUES (Vinson1,note1,1,1 )*/
  ret = sqlite3_exec(db_ctx, sql_buf, NULL, NULL, &zErrMsg);
  if( ret != SQLITE_OK ){
   fprintf(stderr, "SQL error: %s\n", zErrMsg);
   sqlite3_free(zErrMsg);
   return -1;
  }
  if (ret < 0) {
   printf("insert table error! %d\n", ret);
   return -1;
  }
 }
 /*Step4: close*/
 sqlite3_close(db_ctx);
 return 0;
}


编译:


# 嵌入式设备 改成对应工具链:mips-linux-gun-gcc/arm-linux-gun-gcc
gcc sqlite3_demo.c -o sqlite3_test 
-I./sqlite/include  
-L./sqlite/lib/ -lsqlite3 
-ldl 
-lpthread
-lm


  • -I:指定sqlite 头文件包含


  • -L:链接sqlite3 库。


  • ldl:使用库需要


  • lpthread:libsqlite3.a 使用。多线程相关


  • lm:libsqlite3.a 使用。数学库


执行:将生成的程序拷到板子上可直接运行。(./sqlite3_test)生成 MyDBDemo.db 验证:通过交叉编译生成的bin文件 sqlite3,可直接打开查看,我们sqlite3_test生成的数据库。


./sqlite3 MyDBDemo.db



查看数据库信息:


.dump



查看数据库表:


.table


image.png


退出:


.quit


用 Navicat Premium 打开对比查看。


image.png


4. 总结


本文,主要就是嵌入式端sqlite3移植进行介绍,关于数据库的语法和使用,留待读者自行研究。有关sqlite3的接口使用,本文只给出了简单的示例,详细应用,见官网使用说明。


相关文章
|
6月前
|
消息中间件 存储 缓存
【嵌入式软件工程师面经】Linux系统编程(线程进程)
【嵌入式软件工程师面经】Linux系统编程(线程进程)
133 1
|
8天前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
61 13
|
6月前
|
网络协议 算法 Linux
【嵌入式软件工程师面经】Linux网络编程Socket
【嵌入式软件工程师面经】Linux网络编程Socket
200 1
|
6月前
|
Linux
Linux交叉编译+粤嵌LCD实现三色图
Linux交叉编译+粤嵌LCD实现三色图
|
4月前
|
NoSQL Linux C语言
嵌入式GDB调试Linux C程序或交叉编译(开发板)
【8月更文挑战第24天】本文档介绍了如何在嵌入式环境下使用GDB调试Linux C程序及进行交叉编译。调试步骤包括:编译程序时加入`-g`选项以生成调试信息;启动GDB并加载程序;设置断点;运行程序至断点;单步执行代码;查看变量值;继续执行或退出GDB。对于交叉编译,需安装对应架构的交叉编译工具链,配置编译环境,使用工具链编译程序,并将程序传输到开发板进行调试。过程中可能遇到工具链不匹配等问题,需针对性解决。
152 3
|
4月前
|
传感器 人工智能 网络协议
:嵌入式 Linux 及其用途
【8月更文挑战第24天】
219 0
|
5月前
|
Ubuntu 算法 Linux
嵌入式Linux的学习误区
**嵌入式Linux学习误区摘要** 1. **过度聚焦桌面Linux** - 许多学习者误将大量时间用于精通桌面Linux系统(如RedHat、Fedora、Ubuntu),认为这是嵌入式Linux开发的基石。 - 实际上,桌面Linux仅作为开发工具和环境,目标不应是成为Linux服务器专家,而应专注于嵌入式开发工具和流程。 2. **盲目阅读Linux内核源码** - 初学者在不了解Linux基本知识时试图直接研读内核源码,这往往导致困惑和挫败感。 - 在具备一定嵌入式Linux开发经验后再有针对性地阅读源码,才能有效提升技能。
|
6月前
|
SQL Linux 数据库
Linux上sqlite的安装和使用方法以及在QT中如何使用sqlite&笔记总结
Linux上sqlite的安装和使用方法以及在QT中如何使用sqlite&笔记总结
|
6月前
|
消息中间件 安全 Java
【嵌入式软件工程师面经】Linux多进程与多线程
【嵌入式软件工程师面经】Linux多进程与多线程
82 1
|
6月前
|
存储 缓存 Unix
【嵌入式软件工程师面经】Linux文件IO
【嵌入式软件工程师面经】Linux文件IO
54 1