SQLite VFS实现指南与FOpen*

14

我将要为一个嵌入式设备(非Windows系统)使用FOpen,FRead,FWrite,FSeek和FClose实现自定义VFS(虚拟文件系统)。令我惊讶的是,我找不到可用的FOpen *版本的VFS。这将使它更易于在嵌入式设备中移植。

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

在SQLite源代码中,我找到了一些Win、OS2、Linux下的示例VFS,但它们没有太多注释,只有源代码。

如果我使用上述链接和示例来创建自定义VFS,我肯定会错过某些东西。

我的问题是:

  • 是否有关于我遗漏的SQLite VFS的更多文档? 也许有实现指南?
  • 是否有可用的SQLite VFS的Fopen版本?
  • 是否有单元测试代码可用于测试我创建的自定义SQLite VFS?
  • 您想分享SQLite VFS实现方面的建议、评论或经验吗?

如果您在嵌入式设备上运行Linux,为什么需要实现一个新的SQLite VFS? - Noah Watkins
它不是Linux、Windows或OS2,而是修改版的http://www.freertos.org/,不包括Linux/Windows库。 - Steven Smethurst
1
我想你的意思是“实现指南”,而不是“实现公会”。公会是工匠组织(有点像工会,但更像中世纪)。我对你的问题没有一个好答案,但我怀疑fopen和它的朋友们不能用于sqlite,因为它没有锁定机制,语义尤其是与数据何时到达永久存储相关的方面还没有被确定下来,这些都是sqlite需要的。 - zwol
笔误。至于锁定,您可以设置SQLITE_THREADSAFE=0来删除锁定机制的需求,或者您可以使用sqlite3_file结构创建自己的锁定机制,我正在学习中。我已经开始从Win/Linux/OS2的示例中创建VFS,但是没有真正的文档,进展缓慢。 - Steven Smethurst
2个回答

7
你是否注意到在头文件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);

如果你的操作系统标准库没有提供随机数生成器,那么你可能需要实现一个。我建议使用线性反馈移位寄存器,它既小巧又好用。

  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代码搜索!)
祝好运!

4
一种选择是使用基于内存的虚拟文件系统(VFS),然后在完成时将内存直接转储到文件中。参见:http://article.gmane.org/gmane.comp.db.sqlite.general/46450,其中提供了一个支持序列化/反序列化的基于内存的 VFS。
缺点是必须手动将文件写出以使其持久化。如果您的应用程序突然停止,任何对数据库的中间更改都不会被持久化。

这是一个非常有启发性的链接,其中包含了一个VFS实现,但不确定我们是否可以直接使用它(请参见http://osdir.com/ml/sqlite-users/2013-06/msg00067.html)。 - user948581

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接