使用 FOpen* 的 SQLite VFS 实施指南

Posted

技术标签:

【中文标题】使用 FOpen* 的 SQLite VFS 实施指南【英文标题】:SQLite VFS implementation guide lines with FOpen* 【发布时间】:2011-03-23 09:01:09 【问题描述】:

我即将使用 FOpen、FRead、FWrite、FSeek 和 FClose 为 Netburner 嵌入式设备(非 Windows)实现自定义 VFS(虚拟文件系统)。我很惊讶我找不到可用的 VFS 的 FOpen* 版本。它将使其对嵌入式设备更加便携。

我在这里找到了一些关于为 SQLite 创建 VFS 的信息 http://sqlite.org/c3ref/vfs.html 但信息非常详细,我对实施还有很多其他问题。

我在 Win、OS2、Linux 的 SQLite 源代码中有一些示例 VFS,但它们没有很多 cmets,只有源代码。

我可以使用上面链接中提供的信息和示例来创建我的自定义 VFS,但我敢肯定,如果我这样做,我会错过一些东西。

我的问题是:

还有关于我缺少的 SQLite VFS 的更多文档吗?也许是实施指南? 是否有可用的 SQLite VFS 的 Fopen 版本? 创建自定义 SQLite VFS 后,是否有可用的单元测试代码来测试它? 您希望分享的关于实施 SQLite VFS 的建议、cmets 和经验。

【问题讨论】:

如果您在嵌入式设备上运行 Linux,为什么需要实现新的 SQLite VFS? 它不是 Linux、Windows 或 OS2,它是 freertos.org 的修改版本,不包括 Linux/windows 库 我认为您的意思是“实施指南”而不是“实施公会”。行会是工匠的组织(有点像工会,但更多,嗯,中世纪)。我对你的问题没有很好的答案,但我怀疑 fopen 和朋友不能用于 sqlite,因为没有锁定机制,并且语义,特别是与数据何时到达永久存储相关的语义,没有被确定下来因为 sqlite 需要它们。 错字。至于锁定,您可以设置 SQLITE_THREADSAFE=0 以消除对锁定机制的需要,或者您可以使用 sqlite3_file 结构创建自己的,或者我正在学习。我已经开始从 Win/Linux/OS2 的示例中创建一个 VFS,但是如果没有真正的文档,它会很慢。 【参考方案1】:

一种选择是使用基于内存的 VFS,然后在完成后简单地将内存转储到文件中。有关已经支持序列化/反序列化的基于内存的 VFS,请参阅:http://article.gmane.org/gmane.comp.db.sqlite.general/46450。

缺点是您必须手动将文件写出才能保留。如果您的应用程序突然死机,对数据库的任何中间更改都不会被持久化。

【讨论】:

与 VFS 实现的非常有启发性的链接,但不确定我们是否可以按原样使用它(请参阅 osdir.com/ml/sqlite-users/2013-06/msg00067.html)【参考方案2】:

您是否注意到头文件sqlite3.h 中还有一个额外的文档来源?此外,Google 代码搜索是您的朋友。

不要太担心遗漏的东西,这就是测试套件的用途。从名称、文档和示例实现中猜测每个方法的用途;进行初稿实施;在您的目标平台上运行测试;迭代直到条为绿色。通过粗略阅读您引用的界面文档,以下是一些有根据的猜测:

  int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
               int flags, int *pOutFlags);
  int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
  int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);
  int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut);

这些是您常用的文件管理功能。你会注意到xOpen() 又返回一个结构sqlite3_file,它有自己的读写指针方法。

  void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename);
  void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg);
  void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void);
  void (*xDlClose)(sqlite3_vfs*, void*);

这些用于共享库(参见 Linux 上的 dlopen() 手册页)。在嵌入式环境中,您可能可以不实现这些(尝试将它们设置为 NULL)。

  int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut);

如果您的操作系统的标准库还没有提供随机数生成器,您可能需要实现一个随机数生成器。我建议linear feedback register,它虽小但很好。

  int (*xSleep)(sqlite3_vfs*, int microseconds);
  int (*xCurrentTime)(sqlite3_vfs*, double*);
  int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);

这些是时间管理功能,用于连接您的操作系统。

  int (*xGetLastError)(sqlite3_vfs*, int, char *);

您可以通过始终在此处返回 0 来逃脱 :-) 请参阅 os_unix.c 中的 unixGetLastError(感谢 Google 代码搜索!)

祝你好运!

【讨论】:

以上是关于使用 FOpen* 的 SQLite VFS 实施指南的主要内容,如果未能解决你的问题,请参考以下文章

如何在SQLite中添加自己的PRAGMA语句来存储自定义元数据?

我如何解释这个看似函数声明但不符合通常模式的声明?

vfs基本操作(待继续补全)

kernel中文件的读写操作可以使用vfs_read()和vfs_write

VFS文件系统结构分析 与socket

更改核心数据堆栈后使用核心数据创建 SQLite 文件后未更新