SQLite 4.9的 OS 接口或“VFS”(十三)

2024-04-07 10:12
文章标签 接口 sqlite 十三 os 4.9 vfs

本文主要是介绍SQLite 4.9的 OS 接口或“VFS”(十三),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

返回:SQLite—系列文章目录   

上一篇:SQLite字节码引擎(十二)

下一篇:SQLite 4.9的虚拟表机制(十四)

1. 引言

本文介绍了 SQLite OS 可移植性层或“VFS” - 模块位于 SQLite 实现堆栈底部 提供跨操作系统的可移植性。

VFS是Virtual File System(虚拟文件系统)的缩写,是一个计算机文件系统的概念。它允许用户在操作系统中通过不同的协议和存储形式访问文件,而不必考虑底层文件系统的物理实现。这些协议可以是本地文件系统、网络文件系统、FTP、WebDAV、数据库等等。它的作用是为不同的文件系统提供一个统一的接口,使得开发人员能够更轻松地处理和使用文件系统。许多操作系统和软件都使用VFS来管理文件系统,例如Linux操作系统、Windows操作系统等。

2. VFS 与 SQLite 其余部分的关系

SQLite库的内部组织可以看作是 右侧显示的模块堆栈。 Tokenizer、Parser 和 Code Generator 组件用于 处理 SQL 语句并将其转换为可执行程序 使用虚拟机语言或字节码。 粗略地说,这前三层实现了 sqlite3_prepare_v2()。前三名生成的字节码 layers 是一个准备好的语句。 虚拟机模块负责运行 SQL 语句 字节码。B-Tree 模块将数据库文件组织成多个 具有有序键和对数性能的键/值存储。 Pager 模块负责加载数据库的页面 文件存入内存,用于实现和控制事务,以及 用于创建和维护阻止数据库的日志文件 崩溃或电源故障后的损坏。 操作系统接口是一个精简抽象,它提供了一组通用的 用于调整 SQLite 以在不同操作系统上运行的例程。 粗略地说,最底层的四层实现了sqlite3_step()。

这篇文章是关于底层的。

操作系统接口 - 也称为“VFS” - 是SQLite的组成部分 跨操作系统可移植。每当任何其他模块 在SQLite中需要与操作进行通信 系统,它们调用 VFS 中的方法。然后,VFS 调用 满足请求所需的特定于操作的代码。 因此,将 SQLite 移植到新的 操作系统只是编写一个新的操作系统接口层的问题 或“VFS”。

3. 多个 VFS

标准 SQLite 源代码树包含用于 unix 的内置 VFS 和窗户。替代 VFS 可以是 使用 sqlite3_vfs_register() 接口在 start-time 或 run-time 添加。

可以同时注册多个 VFS。 每个 VFS 都有唯一的名称。 同一进程中的单独数据库连接可以使用 同时使用不同的 VFS。就此而言,如果单个 数据库连接打开了多个数据库文件,使用 ATTACH 命令,则每个附加的数据库可能都使用 不同的 VFS。

3.1. 标准 Unix VFS

Unix 构建带有多个内置 VFS。默认 VFS 因为 UNIX 被称为“UNIX”,用于大多数应用程序。 在 unix 中可能找到的其他 VFS(取决于编译时 选项)包括:

  1. unix-dotfile - 使用点文件锁定而不是 POSIX 咨询锁。

  2. unix-excl - 获取并持有独占锁 数据库文件,阻止其他进程访问 数据库。还将 wal-index 保持在堆中而不是 共享内存。

  3. unix-none - 所有文件锁定操作都是无操作的。

  4. unix-namedsem - 使用命名信号量进行文件锁定。 仅限 VXWorks。

各种 unix VFS 的区别仅在于它们处理文件锁定的方式 - 它们彼此共享大部分共同的实现,并且 都位于同一个 SQLite 源文件中:os_unix.c。 请注意,除了 “unix” 和 “unix-excl” 之外,各种 unix VFS 都 使用不兼容的锁定实现。如果两个进程正在访问 使用不同 unix VFS 的同一 SQLite 数据库,它们可能 看不到彼此的锁,最终可能会相互干扰, 导致数据库损坏。特别是“unix-none”VFS 根本不会锁定,如果 由两个或多个数据库连接同时使用。 鼓励程序员只使用“unix”或“unix-excl”,除非 有令人信服的理由不这样做。

3.2. 标准 Windows VFS

Windows 版本还附带了多个内置 VFS。默认值 Windows VFS 称为“win32”,用于大多数应用程序。 可能在 Windows 版本上找到的其他 VFS 包括:

  1. win32-longpath - 类似于“win32”,但路径名可以 长度最大为 65534 字节,而路径名的最大长度为 “win32”中的 1040 字节。

  2. Win32-None - 所有文件锁定操作都是无操作的。

  3. win32-longpath-none - “win32-longpath”的组合 和“win32-none” - 支持长路径名,并且全部锁定 操作是无操作的。

与 unix 一样,各种 Windows VFS 的大部分代码都是共享的。

3.3. 指定要使用的 VFS

始终有一个 VFS 是默认的 VFS。在 unix 系统上, “unix”VFS 作为默认值出现,在 Windows 上它是“win32”。 如果未执行其他操作,则将使用新的数据库连接 默认 VFS。

可以通过注册或重新注册 VFS 使用带有第二个参数的 sqlite3_vfs_register() 接口 的 1.因此,如果 (unix) 进程想要始终使用“unix-nolock”VFS 代替“UNIX”,以下代码将起作用:

sqlite3_vfs_register(sqlite3_vfs_find("unix-nolock"), 1);

也可以将备用 VFS 指定为 sqlite3_open_v2() 函数的第 4 个参数。例如:

int rc = sqlite3_open_v2("demo.db", &db, SQLITE_OPEN_READWRITE, "unix-nolock");

最后,如果启用了 URI 文件名,则替代方法 可以使用 URI 上的“vfs=”参数指定 VFS。这种技术 适用于 sqlite3_open()、sqlite3_open16()、sqlite3_open_v2() 和 当新数据库通过 ATTACH 连接到现有数据库连接时。 例如:

ATTACH 'file:demo2.db?vfs=unix-none' AS demo2;

URI 指定的 VFS 具有最高优先级。在那之后 指定为 sqlite3_open_v2() 的第四个参数的 VFS。这 如果未指定 VFS,则使用默认 VFS。

3.4. VFS垫片

从 SQLite 堆栈的上层来看,每个 打开数据库文件仅使用一个 VFS。 但在实践中,特定的 VFS 可能会 只是成为另一个做真正工作的 VFS 的薄包装器。 我们将包装器 VFS 称为“填充码”。

填充码的一个简单示例是“vfstrace”VFS。这是一个 VFS (在 test_vfstrace.c 源文件中实现),用于写入与每个 VFS 方法调用关联的消息 到日志文件中,然后将控制权传递给另一个 VFS 以执行实际操作 工作。

3.5. 其他示例 VFS

以下是公开提供的其他 VFS 实现 SQLite源代码树:

  • appendvfs.c - 此 VFS 允许将 SQLite 数据库附加到某些 其他文件。例如,这可用于追加 SQLite 数据库 到可执行文件的末尾,这样,当运行时,它可以很容易地 找到追加的数据库。命令行 shell 将使用此 VFS(如果使用 --append 选项启动)及其 .archive 命令 将在给定 --append 标志的情况下使用它。

  • test_demovfs.c - 此文件实现了一个名为“demo”的非常简单的 VFS,它使用 POSIX 功能,例如 open(), read(), write(), fsync(), close(), fsync(), fsync(), sleep(), time(), 等等。此 VFS 仅适用于 unix 系统。但事实并非如此 旨在替代默认使用的标准“unix”VFS 在 UNIX 平台上。“演示”VFS刻意保持非常简单 这样它就可以用作学习辅助工具或构建模板 其他 VFS 或用于将 SQLite 移植到新的操作系统。

  • test_quota.c - 此文件实现一个名为“quota”的填充码,该填充码强制执行累积 数据库文件集合的文件大小限制。辅助 接口用于定义“配额组”。配额组是一个 文件集(数据库文件、日志和临时文件),其 名称都与 GLOB 模式匹配。所有文件大小的总和 在每个配额组中跟踪,以及该总和是否超过阈值 为配额组定义后,将调用回调函数。那 回调可以增加阈值,也可以导致操作 这将超过配额,并因SQLITE_FULL错误而失败。此填充码的用途之一用于强制执行 Firefox 中应用程序数据库的资源限制。

  • test_multiplex.c - 此文件实现一个填充码,该填充码允许数据库文件超过 底层文件系统的最大文件大小。这个垫片呈现 SQLite 上六层的接口,使其看起来像 正在使用非常大的文件,而实际上每个这样的大文件 在底层系统上拆分为许多较小的文件。 例如,此填充码已用于允许数据库增长 FAT16 文件系统上大于 2 GB。

  • test_onefile.c - 此文件实现了一个名为“fs”的演示 VFS,它显示了 SQLite 如何 可以在缺少文件系统的嵌入式设备上使用。内容是 直接写入基础媒体。派生自 VFS 演示代码可以由数量有限的小工具使用 闪存,使 SQLite 充当闪存的文件系统 在设备上。

  • test_journal.c - 此文件实现了 SQLite 测试期间使用的填充码,用于验证 数据库和回滚日志按正确的顺序写入,并且 在适当的时间“同步”,以保证数据库 可以随时从断电中恢复硬复位。垫片 检查数据库操作和回滚的几个不变量 日志,并在违反任何这些不变量时引发异常。 反过来,这些不变量确保数据库始终是可恢复的。 使用此填充码运行大量测试用例可提供额外的 保证SQLite数据库不会因意外而损坏 电源故障或设备重置。

  • test_vfs.c - 此文件实现了可用于模拟文件系统故障的填充码。 此填充码在测试期间用于验证 SQLite 的响应是否合理 硬件故障或其他错误情况,例如用完 的文件系统空间,难以在实际系统上进行测试。

在核心 SQLite 源代码中还有其他 VFS 实现 库和可用的扩展。上面的列表并不意味着 详尽无遗,但仅代表可以 使用VFS接口实现。

4. VFS实现

新的 VFS 是通过子类化三个对象来实现的:

  • sqlite3_vfs
  • sqlite3_io_methods
  • sqlite3_file

sqlite3_vfs对象定义 VFS 和内核的名称 实现操作系统接口的方法,例如 如检查文件是否存在、删除文件、创建文件 以及打开和用于读取和/或写入、转换文件名 变成他们的规范形式。sqlite3_vfs对象还包含 从操作系统获取随机性的方法,用于 暂停进程(休眠)并查找当前日期和 时间。

sqlite3_file 对象表示打开的文件。 sqlite3_vfs 的 xOpen 方法在打开文件时构造一个 sqlite3_file 对象。sqlite3_file跟踪 打开文件时的状态。

sqlite3_io_methods对象保存用于交互的方法 使用打开的文件。每个sqlite3_file都包含一个指向 适合于文件的 sqlite3_io_methods 对象 代表。sqlite3_io_methods对象包含要执行的方法 诸如从文件中读取和写入,以截断文件之类的操作, 要刷新对持久性存储的任何更改,请查找 file,以锁定和解锁文件,以及关闭文件并销毁 sqlite3_file对象。

为新 VFS 编写代码涉及构造 sqlite3_vfs对象,然后使用 对 sqlite3_vfs_register() 的调用。VFS 实现还 为 sqlite3_file 和 sqlite3_io_methods 提供子类,但 这些对象不会直接注册到 SQLite。相反,sqlite3_file 对象是从 sqlite3_vfs 的 xOpen 方法返回的,并且 sqlite3_file 对象指向实例 sqlite3_io_methods对象。

这篇关于SQLite 4.9的 OS 接口或“VFS”(十三)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/882317

相关文章

C#实现文件读写到SQLite数据库

《C#实现文件读写到SQLite数据库》这篇文章主要为大家详细介绍了使用C#将文件读写到SQLite数据库的几种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下... 目录1. 使用 BLOB 存储文件2. 存储文件路径3. 分块存储文件《文件读写到SQLite数据库China编程的方法》博客中,介绍了文

Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密解密

加密效果: 解密后的数据就是正常数据: 后端:使用的是spring-cloud框架,在gateway模块进行操作 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version></dependency> 编写一个AES加密

java线程深度解析(一)——java new 接口?匿名内部类给你答案

http://blog.csdn.net/daybreak1209/article/details/51305477 一、内部类 1、内部类初识 一般,一个类里主要包含类的方法和属性,但在Java中还提出在类中继续定义类(内部类)的概念。 内部类的定义:类的内部定义类 先来看一个实例 [html]  view plain copy pu

模拟实现vector中的常见接口

insert void insert(iterator pos, const T& x){if (_finish == _endofstorage){int n = pos - _start;size_t newcapacity = capacity() == 0 ? 2 : capacity() * 2;reserve(newcapacity);pos = _start + n;//防止迭代

JavaSE(十三)——函数式编程(Lambda表达式、方法引用、Stream流)

函数式编程 函数式编程 是 Java 8 引入的一个重要特性,它允许开发者以函数作为一等公民(first-class citizens)的方式编程,即函数可以作为参数传递给其他函数,也可以作为返回值。 这极大地提高了代码的可读性、可维护性和复用性。函数式编程的核心概念包括高阶函数、Lambda 表达式、函数式接口、流(Streams)和 Optional 类等。 函数式编程的核心是Lambda

京东物流查询|开发者调用API接口实现

快递聚合查询的优势 1、高效整合多种快递信息。2、实时动态更新。3、自动化管理流程。 聚合国内外1500家快递公司的物流信息查询服务,使用API接口查询京东物流的便捷步骤,首先选择专业的数据平台的快递API接口:物流快递查询API接口-单号查询API - 探数数据 以下示例是参考的示例代码: import requestsurl = "http://api.tanshuapi.com/a

股票数据接口-陈科肇

陈科肇 新浪财经 sz-深圳sh-上海历史分价表:http://market.finance.sina.com.cn/pricehis.php?symbol=sz000506&startdate=2016-12-27&enddate=2016-12-27历史成交明细(当日成交明细):http://vip.stock.finance.sina.com.cn/quotes_service/v

sqlite不支持中文排序,采用java排序

方式一 不支持含有重复字段进行排序 /*** sqlite不支持中文排序,改用java排序* 根据指定的对象属性字段,排序对象集合,顺序* @param list* @param field* @return*/public static List sortListByField(List<?> list,String field){List temp = new ArrayList(

Cmake之3.0版本重要特性及用法实例(十三)

简介: CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏: 多媒体系统工程师系列【原创干货持续更新中……】🚀 优质视频课程:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧

Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.B

一个bug日志 FATAL EXCEPTION: main03-25 14:24:07.724: E/AndroidRuntime(4135): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.syyx.jingubang.ky/com.anguotech.android.activity.Init