Linux 物联网网关主控系统-Web部分(一)
- [一、Linux 目录操作](#一、Linux 目录操作)
-
- 1.目录操作的项目应用场景
- 2.核心函数解析
-
- 1.opendir:打开目录
- [2. readdir:读取目录内容](#2. readdir:读取目录内容)
- 3.closedir:关闭目录
- 3.代码示例
- 二、SQLite
-
- 1.SQLite基础
-
- [1.嵌入式 Linux 常用数据库](#1.嵌入式 Linux 常用数据库)
- [2.SQLite3 发展背景](#2.SQLite3 发展背景)
- [3.SQLite3 核心特性](#3.SQLite3 核心特性)
- [4.SQLite3 安装操作(Ubuntu 环境)](#4.SQLite3 安装操作(Ubuntu 环境))
- [2.SQLite3 数据类型和约束](#2.SQLite3 数据类型和约束)
-
- [1.SQLite3 主要数据类型](#1.SQLite3 主要数据类型)
- [2.SQLite3 其它拓展数据类型](#2.SQLite3 其它拓展数据类型)
- [3.SQLite3 表的约束](#3.SQLite3 表的约束)
- 3.表操作:增删改查
- [4.Sqlite C编程接口](#4.Sqlite C编程接口)
一、Linux 目录操作
1.目录操作的项目应用场景
在本项目中,摄像头拍摄的图片会存储在/www/pice目录下,若要实现历史图片展示功能,就需要通过目录操作函数遍历该目录下的所有图片文件,获取文件名后再进行后续的读取和展示处理,这也是嵌入式开发中目录操作最典型的应用场景之一。
2.核心函数解析
1.opendir:打开目录
c
DIR *opendir(const char *name);
打开参数name指定的目录,返回DIR * 类型的目录流(类似文件操作的文件描述符),后续对目录的读取、遍历操作均基于此返回值,作用与文件操作的open()类似。
成功:返回 DIR * 型的目录流指针;
失败:返回 NULL。
2. readdir:读取目录内容
c
struct dirent *readdir(DIR *dir);
读取参数dir(opendir 返回的目录流)指向的目录,每次调用返回目录中的下一个目录项,遍历至目录末尾时停止。
成功:返回下一个目录项的struct dirent指针;
失败 / 读取到目录末尾:返回 NULL。
关键结构体:struct dirent
c
struct dirent{
ino_t d_ino; // 此目录项的inode节点号
off_t d_off; // 目录文件开头到当前目录项的位移
signed short d_reclen; // d_name的长度(不含NULL结束符)
unsigned char d_type; // 文件类型(核心字段,用于判断文件类型)
char d_name[256]; // 文件名(核心字段)
};
3.closedir:关闭目录
c
int closedir(DIR *dir);
关闭参数dir指向的目录流,释放相关资源,作用与文件操作的close()类似,遍历目录后必须调用,避免资源泄漏。
c
成功:返回 0;
失败:返回 - 1,错误原因存于errno中。
3.代码示例
c
#include<stdio.h>
#include<dirent.h>
#include<stdlib.h> // 包含exit()函数
// 定义图片存储目录
#define DIRNAME "/www/pice"
// 定义最大图片数(可选)
#define PHOTO_NUM_MAX 100
int main()
{
// 定义目录流指针和目录项结构体指针
DIR *dir;
struct dirent *dirp;
// 用于统计文件序号
int total_num = 1;
// 第一步:打开目录,做错误处理
if((dir = opendir(DIRNAME)) == NULL)
{
perror("fail to opendir"); // 打印错误信息
exit(1); // 异常退出
}
// 第二步:循环读取目录项,直至遍历结束
while((dirp = readdir(dir)) != NULL)
{
// 打印文件序号(三位补0)和文件名
printf("%03d:%s\t", total_num++, dirp->d_name);
}
printf("\n"); // 换行,优化输出格式
// 第三步:关闭目录,释放资源
closedir(dir);
return 0;
}
PS:如果文件夹里面还有文件夹
重点 1:原代码不区分文件 / 文件夹
文件夹会被当作普通名称打印,不会进入读取。
重点 2:判断文件 / 文件夹的方法
c
dirp->d_type == DT_REG // 普通文件
dirp->d_type == DT_DIR // 文件夹
重点 3:两种处理方式
跳过文件夹:只打印图片 / 文件
递归遍历:进入子文件夹继续读(嵌入式项目最常用)
二、SQLite
1.SQLite基础
1.嵌入式 Linux 常用数据库
在嵌入式 Linux 开发中,主流的轻量级数据库主要有SQLite、Firebird、Berkeley DB、eXtremeDB,其中 SQLite 是最常用的选择;而传统大型数据库(Oracle、DB2、SQL2000、MySQL)因体积、资源占用等问题,不适合嵌入式场景。
2.SQLite3 发展背景
1.作者:D.RichardHipp
2.开发初衷:打造一款简单的嵌入式 SQL 数据库,基于 GNU DBM 哈希库做后台,无需安装和管理支持
3.版本发布:2000 年 8 月发布 SQLite 1.0 版,是一款轻量级嵌入式数据库,适配嵌入式开发的轻量、低资源需求。
3.SQLite3 核心特性
这是 SQLite3 适配嵌入式开发的关键,也是其区别于传统大型数据库的核心优势,共 6 大核心特性:
1.零配置:无需安装和任何管理配置,直接使用,适配嵌入式设备的简易部署需求;
2.单文件存储:整个数据库的所有数据都储存在单一磁盘文件中,便于管理和移植;
3.跨平台兼容:数据库文件可在不同字节顺序的机器间自由共享,无平台适配障碍;
4.大容量支持:单数据库文件大小最大可支持2TB,满足嵌入式场景的存储需求;
5.超轻量:全部源码仅约 3 万行 C 代码,编译后体积仅 250KB,对嵌入式设备的内存、存储资源占用极低;
6.高性能:对数据的操作速度,比目前主流的大多数数据库更快,适配嵌入式设备的低性能硬件环境。
4.SQLite3 安装操作(Ubuntu 环境)
源码下载地址 https://www.sqlite.org/index.html(用下面的 apt-get就不用这个了)
嵌入式开发中需安装应用程序+开发库 / 头文件(C 语言操作数据库必须装),也可安装图形化工具简化操作,具体命令如下:
核心安装(必装)
c
c
图形化工具安装(可选,便于可视化操作)
c
sudo apt-get install sqlitebrowser
查看版本
c
# 进入sqlite3环境
sqlite3
# 查看版本信息
.version
c
SQLite version 3.11.0 2016-02-15 17:29:24 3d862f207e3adc00f78066799ac5a8c282430a5f
2.SQLite3 数据类型和约束
1.SQLite3 主要数据类型

2.SQLite3 其它拓展数据类型

3.SQLite3 表的约束
约束是对数据表中列的额外限制属性,用于规范列的取值规则,避免无效、错误数据的插入,常用约束共 6 种,各约束的核心作用如下:

3.表操作:增删改查
SQLite3 中对数据表的核心操作即为增、删、改、查,操作前需先创建数据库和对应的数据表,所有操作均通过 SQL 语句实现,以下结合教学管理数据库 jxgl.db、学生表 stu的实战场景,梳理完整操作流程,包含核心命令、实操示例及注意事项。
前置准备
- 创建并打开数据库
c
# 终端执行,创建并进入jxgl.db数据库(不存在则创建,存在则打开)
sqlite3 jxgl.db
- 创建 stu 学生表
c
CREATE TABLE IF NOT EXISTS stu (
Sno integer primary key,
Sname text not null,
Ssex text,
Sage integer check(Sage>14),
Sdept text default 'CS'
);
- 验证表创建成功
c
# 查看当前数据库中的所有表
.table
输出:stu
1.增:插入数据(INSERT)
c
INSERT INTO 表名 VALUES (字段值1,字段值2,字段值3,...);
向 stu 表插入 4 条学生数据,字段顺序与建表时一致(学号、姓名、性别、年龄、专业):
c
INSERT INTO STU VALUES(95001,'李勇','M',20,'CS');
INSERT INTO STU VALUES(95002,'刘晨','F',19,'IS');
INSERT INTO STU VALUES(95003,'王敏','F',18,'MA');
INSERT INTO STU VALUES(95004,'张立','M',18,'IS');
辅助命令:验证插入结果
c
# 查看表中所有数据(需先设置列对齐和显示表头,优化输出)
.headers on
.mode column
select * from stu;
2.查:查询数据(SELECT)
c
# 查询表中所有字段的所有数据
SELECT * FROM 表名;
# 查询指定字段的指定数据(配合WHERE条件筛选)
SELECT 字段1,字段2 FROM 表名 WHERE 筛选条件;
实操示例
c
# 1. 查询stu表中所有学生的所有信息
select * from stu;
# 2. 筛选查询:查询专业为CS的学生姓名和学号
select Sno,Sname from stu where Sdept='CS';
# 3. 条件筛选:查询年龄大于18的学生信息
select * from stu where Sage>18;
3.改:修改数据(UPDATE)
c
UPDATE 表名 SET 字段1=新值1,字段2=新值2 WHERE 筛选条件;
实操示例
将 stu 表中张立的年龄修改为 29:
c
UPDATE stu SET sage=29 WHERE sname='张立';
验证修改结果
c
select * from stu where sname='张立';
4.删:删除数据(DELETE)
c
DELETE FROM 表名 WHERE 筛选条件;
注意:必须加 WHERE 条件,否则会删除表中所有数据!
实操示例
删除 stu 表中王敏的这条记录:
c
delete from stu where sname = '王敏';
验证删除结果
c
select * from stu;
4.Sqlite C编程接口
前面的终端增删改查 → 人手动操作数据库(测试 / 调试用)
这里的C 编程接口 → 程序自动操作数据库(项目开发实际使用)
