• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • Sqlite3源碼學習(5)OS的接口VFS

        之前講了那么多的環境搭建,現在終于可以學習源碼了。官方有一篇講解VFS的文檔,對理解sqlite3VFS有很大的幫助:

    http://www.sqlite.org/vfs.html

    1.VFS簡介

          VFS也就是所謂的虛擬文件系統,因為sqlite3運行在不同的平臺上會有不同的文件系統,VFS就是對不同的文件系統做一個統一的接口。

          先來看一下一張圖:

                 clip_image001[4]

    這張圖展示了sqlite3的軟件層次結構,主要分為前端和后端,OS層位于最底層,是和系統的磁盤文件存儲直接打交道,在OS層里封裝了VFS

    Sqlit3VFS體現了跨平臺的特性,雖然不同文件系統的實現是不一樣的,但是接口都是相同的。

    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_vfssqlite3_io_methods結構體里的一系列方法,即函數指針的實體函數的實現,sqlite3_file結構體作為一個文件句柄的傳入參數,在open時會將sqlite3_file指針強制轉為特定的file指針,該file結構體從sqlite3_file繼承,感覺有點像C++sqlite3_file相當于一個基類,在不同VFS下有不同的派生類。

    3.VFS的類型

    win下的vfswin32win32-longpathwin32-nonewin32-longpath-none,默認使用的是win32 vfs;在類unix系統下的vfsunixunix-dotfilunix-exclunix-none等,默認使用的是unix vfssqlite3內核在初始化時調用sqlite3_os_init()函數來注冊vfssqlite3_os_init()在不同系統下有不同的實現。

    除了上面這些在test文件里還實現了一些其他的vfs

    test_demovfs.c:最簡單的vfs,可以學習vfs的基本實現

    test_onefile.c:用于嵌入式設備的vfs

    test_quota.c:實現了一個名為quotavfs、功能暫時不清楚,具體見官方文檔

    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地址pVfsmakeDflt,將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


      關于sqlite3tcl的使用參考以下文檔
    http://nut.sourceforge.net/drh.html
    http://www.sqlite.org/tclsqlite.html
     
     
    版權聲明:本文為pfysw原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/pfysw/article/details/78701854

    智能推薦

    sqlite3的簡單用法

    sqlite3的簡單用法 安裝sqlite3 基本用法 打開數據庫 sqlite3 test.db 查看表 .tables 可以使用圖形化工具navicat來創建的查看數據庫 sqlite3 C/C++接口 Example 編譯 需要在編譯選項上加入-lsqlite3 如果使用的編輯器,比如codeblocks,按如下位置配置 出現fatal error: sqlite3.h: No such f...

    SQLite3的安裝與使用

    SQLite3的安裝與使用 SQLite下載 我是64位機,下載下面的兩個解壓就好 然后解壓配置環境變量Path H:\java\SQLlite\sqlite-tools-win32-x86-3310100 我的安裝目錄是在這里,所以Path配置地址就是這個 測試使用 在dos界面中輸入sqlite3查看 輸入sqlite3,顯示下面內容說明成功 創建數據庫 生成DB文件 創建表 新增數據 Nav...

    Sqlite3的安裝及應用

            SQLite,是一款輕型的數據庫,是遵守ACID的關系型數據庫管理系統,它包含在一個相對小的C庫中。SQLite是D.Richard Hipp用C語言編寫的開源嵌入式數據庫引擎,它支持大多數的SQL92標準。它的設計目標是嵌入式的,而且目前已經在很多嵌入式產品中使用了它,它占用資源非常的低,在嵌入式設備中,可能只需要幾百K的內存就夠了。它能夠...

    Django sqlite3的實際應用

    db.html(模板) models.py views.py#向數據庫member里進行增刪改查操作 urls.py#訪問網址 setting.py#數據庫配置 出現編碼問題 名前、年目、メール、時間、地點從數據庫獲取。 命令操作 遇到問題 models.py增加字段后,需要重新生成數據表時,刪除migrations目錄,以及數據庫里有關的數據表, 重新執行命令生成。(有時執行命令報錯,參照刪除即...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    猜你喜歡

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    精品国产乱码久久久久久蜜桃不卡