Sqlite3源码学习(5)OS的接口VFS
来源:互联网 发布:农村淘宝前景 编辑:程序博客网 时间:2024/05/21 06:19
之前讲了那么多的环境搭建,现在终于可以学习源码了。官方有一篇讲解VFS的文档,对理解sqlite3的VFS有很大的帮助:
http://www.sqlite.org/vfs.html
1.VFS简介
VFS也就是所谓的虚拟文件系统,因为sqlite3运行在不同的平台上会有不同的文件系统,VFS就是对不同的文件系统做一个统一的接口。
先来看一下一张图:
这张图展示了sqlite3的软件层次结构,主要分为前端和后端,OS层位于最底层,是和系统的磁盘文件存储直接打交道,在OS层里封装了VFS。
Sqlit3的VFS体现了跨平台的特性,虽然不同文件系统的实现是不一样的,但是接口都是相同的。
2.VFS的组成
VFS最基本的对象是sqlite3_vfs结构体:
typedef struct sqlite3_vfs sqlite3_vfs;typedef void (*sqlite3_syscall_ptr)(void);struct sqlite3_vfs { int iVersion; /* Structure version number (currently 3) */ int szOsFile; /* Size of subclassed sqlite3_file */ int mxPathname; /* Maximum file pathname length */ sqlite3_vfs *pNext; /* Next registered VFS */ const char * zName; /* Name of this virtual file system */ void *pAppData; /* Pointer to application-specific data */ 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); 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*); int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); int (*xSleep)(sqlite3_vfs*, int microseconds); int (*xCurrentTime)(sqlite3_vfs*, double*); int (*xGetLastError)(sqlite3_vfs*, int, char *); /* ** The methods above are in version 1 of the sqlite_vfs object ** definition. Those that follow are added in version 2 or later */ int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*); /* ** The methods above are in versions 1 and 2 of the sqlite_vfs object. ** Those below are for version 3 and greater. */ int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr); sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName); const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName); /* ** The methods above are in versions 1 through 3 of the sqlite_vfs object. ** New fields may be appended in future versions. The iVersion ** value will increment whenever this happens. */};
结构体里定义了一系列函数指针,几个关键的地方是:
int szOsFile: file结构体的大小,继承自sqlite3_file,分配空间时要用
sqlite3_vfs *pNext;:指向下一个vfs节点的指针
const char * zName:vfs的名字
void *pAppData:这个指针指向一个存储了各种文件io操作方法的结构体地址,如win下是
typedef struct winVfsAppData winVfsAppData;struct winVfsAppData { const sqlite3_io_methods *pMethod; /* The file I/O methods to use. */ void *pAppData; /* The extra pAppData, if any. */ BOOL bNoLock; /* Non-zero if locking is disabled. */};static winVfsAppData winAppData = { &winIoMethod, /* pMethod */ 0, /* pAppData */ 0 /* bNoLock */};
要实现一个VFS实体,就是实现sqlite3_vfs和sqlite3_io_methods结构体里的一系列方法,即函数指针的实体函数的实现,sqlite3_file结构体作为一个文件句柄的传入参数,在open时会将sqlite3_file指针强制转为特定的file指针,该file结构体从sqlite3_file继承,感觉有点像C++,sqlite3_file相当于一个基类,在不同VFS下有不同的派生类。
3.VFS的类型
在win下的vfs有win32、win32-longpath、win32-none和win32-longpath-none,默认使用的是win32 vfs;在类unix系统下的vfs有unix、unix-dotfil、unix-excl、unix-none等,默认使用的是unix vfs。sqlite3内核在初始化时调用sqlite3_os_init()函数来注册vfs,sqlite3_os_init()在不同系统下有不同的实现。
除了上面这些在test文件里还实现了一些其他的vfs如
test_demovfs.c:最简单的vfs,可以学习vfs的基本实现
test_onefile.c:用于嵌入式设备的vfs
test_quota.c:实现了一个名为quota的vfs、功能暂时不清楚,具体见官方文档
test_multiplex.c:这个vfs好像是用来处理大文件,具体见官方文档
test_journal.c:这个vfs主要测试回滚日志的存储
test_vfs.c:这个文件主要实现文件系统出错的模拟
4.VFS的注册和使用
如果vfs没有在sqlite3_os_init()里注册,那么就要使用sqlite3_vfs_register函数来注册,其实现如下:
int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){ MUTEX_LOGIC(sqlite3_mutex *mutex;)#ifndef SQLITE_OMIT_AUTOINIT int rc = sqlite3_initialize(); if( rc ) return rc;#endif#ifdef SQLITE_ENABLE_API_ARMOR if( pVfs==0 ) return SQLITE_MISUSE_BKPT;#endif MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) sqlite3_mutex_enter(mutex); vfsUnlink(pVfs); if( makeDflt || vfsList==0 ){ pVfs->pNext = vfsList; vfsList = pVfs; }else{ pVfs->pNext = vfsList->pNext; vfsList->pNext = pVfs; } assert(vfsList); sqlite3_mutex_leave(mutex); return SQLITE_OK;}
这个函数的传入参数为要注册的vfs地址pVfs和makeDflt,将pVfsv存储到链表中,vfsList为头节点,如果makeDflt不为0,那么pVfs作为头节点,否则pVfs指向头节点的下一个节点,这里添加节点时需要加锁,防止多线程时被重入。
注册后就可以通过调用sqlite3_open_v2()来替换vfs,下面以demo vfs为示例
sqlite3_vfs_register(sqlite3_demovfs(), 1);//注册 int rc = sqlite3_open_v2("demo.db", &db, SQLITE_OPEN_READWRITE, "demo");//使用demo vfs替换默认的vfs在tcl下的使用时,先运行上篇讲的tcl扩展程序,输入以下命令
register_demovfs #注册demo vfs
sqlite3 db example1.db -vfs demo #打开example1.db数据库,并选择demo vfs替换默认的vfs。
db eval {CREATE TABLE t1(a TEXT, b INTEGER)} #新建表
db eval {
INSERT INTO t1 VALUES('one',1);
INSERT INTO t1 VALUES('two',2);
INSERT INTO t1 VALUES(NULL,3);
} #插入行
puts [db eval {SELECT * FROM t1}] #显示表的所有行,最后输出结果:
one 1 two 2 {} 3
关于sqlite3中tcl的使用参考以下文档
http://nut.sourceforge.net/drh.html
http://www.sqlite.org/tclsqlite.html
- Sqlite3源码学习(5)OS的接口VFS
- Sqlite3源码学习(6)demovfs分析
- jboss的VFS的学习
- sqlite3的C接口
- SQLITE3的C接口
- xpl同学的vfs学习笔记(上)(强烈推荐)
- xpl同学的vfs学习笔记(下)(强烈推荐)
- TCP/IP源码学习(47)——socket与VFS的关联
- vfs学习
- sqlite3的c/c++接口
- Sqlite3的学习笔记
- Apache VFS(6): 几个重要的概念性接口
- 应用程序和VFS之间的接口是系统调用
- sqlite3源码学习(7) uri解析
- 学习Sqlite3 (一)
- 学习sqlite3(二)
- 学习sqlite3(三)
- jQuery源码学习---插件接口的设计
- SAP MM模块相关透明表收集
- python2.7+opencv3.1人脸识别
- EventBus的简单使用
- java多线程(6)线程池
- SpringBoot的入门搭建(四)
- Sqlite3源码学习(5)OS的接口VFS
- 阿里数据源druid
- 反编译apk文件
- 377. Combination Sum IV
- 正确把控seo优化工作流程
- Serializable
- Ubuntu16.04 通过网线直连树莓派
- AUTOSAR 基础软件的内在安全
- 做一个个人主页