• <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源碼學習(14) 模擬靜態變量

    標簽: sqlite3  源碼  內存分配

    /*
    ** When SQLITE_OMIT_WSD is defined, it means that the target platform does
    ** not support Writable Static Data (WSD) such as global and static variables.
    ** All variables must either be on the stack or dynamically allocated from
    ** the heap.  When WSD is unsupported, the variable declarations scattered
    ** throughout the SQLite code must become constants instead.  The SQLITE_WSD
    ** macro is used for this purpose.  And instead of referencing the variable
    ** directly, we use its constant as a key to lookup the run-time allocated
    ** buffer that holds real variable.  The constant is also the initializer
    ** for the run-time allocated buffer.
    **
    ** In the usual case where WSD is supported, the SQLITE_WSD and GLOBAL
    ** macros become no-ops and have zero performance impact.
    */

           如果目標平臺不支持靜態變量和全局變量,所有變量都需要從棧或堆里分配,這時候全局變量的聲明都是constsqlite以變量的地址作為關鍵字來映射堆中的一片地址空間,從而對這個地址的讀寫來代替對靜態變量的讀寫。

    使用時需要打開SQLITE_OMIT_WSD宏定義,以全局變量sqlite3Config為例,首先把sqlite3Config定義成const變量,再傳入變量的地址和變量的長度,返回堆中映射的地址。

    #ifdef SQLITE_OMIT_WSD
      #define SQLITE_WSD const
      #define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v)))//傳入地址和長度
      #define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config)
      int sqlite3_wsd_init(int N, int J);
      void *sqlite3_wsd_find(void *K, int L);
    #else
      #define SQLITE_WSD
      #define GLOBAL(t,v) v
      #define sqlite3GlobalConfig sqlite3Config
    #endif
    SQLITE_WSD struct Sqlite3Config sqlite3Config//定義const變量

    實現時,首先要有一個pGlobal來管理堆中申請的空間,pGlobal的類型是ProcessLocalStorage,結構定義如下:

    #define PLS_HASHSIZE 43
    
    typedef struct ProcessLocalStorage ProcessLocalStorage;
    typedef struct ProcessLocalVar ProcessLocalVar;
    
    struct ProcessLocalStorage {
      ProcessLocalVar *aData[PLS_HASHSIZE];
      int nFree;
      u8 *pFree;
    };
    
    struct ProcessLocalVar {
      void *pKey;
      ProcessLocalVar *pNext;
    };
    
    static ProcessLocalStorage *pGlobal = 0; 

    其中pGlobal-> aData映射傳進來的靜態變量的實際地址。 

     

    初始化時首先申請總的空間N + sizeof(ProcessLocalStorage) + J*sizeof(ProcessLocalVar);其中N是變量的總空間,J是變量的個數

    int sqlite3_wsd_init(int N, int J){
      if( !pGlobal ){
        int nMalloc = N + sizeof(ProcessLocalStorage) + J*sizeof(ProcessLocalVar);
        pGlobal = (ProcessLocalStorage *)malloc(nMalloc);
        if( pGlobal ){
          memset(pGlobal, 0, sizeof(ProcessLocalStorage));
          pGlobal->nFree = nMalloc - sizeof(ProcessLocalStorage);
          pGlobal->pFree = (u8 *)&pGlobal[1];
        }
      }
    
      return pGlobal ? SQLITE_OK : SQLITE_NOMEM;
    }

    其中pGlobal->pFree是未使用的空間,已經使用的空間作為靜態變量的映射存在hash表里,相同hash值的變量通過鏈表連接在一起。

    clip_image002[4]

    使用時只要調用函數void *sqlite3_wsd_find(void *K, int L)就可以了,其中K是變量的原始地址,L是變量所占的空間長度。

    void *sqlite3_wsd_find(void *K, int L){
      int i;
      int iHash = 0;
      ProcessLocalVar *pVar;
    
      /* Calculate a hash of K */
      /*把變量的地址K通過一定的算法得到hash值 iHash */
      for(i=0; i<sizeof(void*); i++){
        iHash = (iHash<<3) + ((unsigned char *)&K)[i];
      }
      iHash = iHash%PLS_HASHSIZE;
    
      /* Search the hash table for K. */
      /*在iHash的hash元素鏈表里查找關鍵字是K的元素*/
      for(pVar=pGlobal->aData[iHash]; pVar && pVar->pKey!=K; pVar=pVar->pNext);
    
      /* If no entry for K was found, create and populate a new one. */
      if( !pVar ){
        int nByte = ROUND8(sizeof(ProcessLocalVar) + L);//申請的空間總長度
        assert( pGlobal->nFree>=nByte );
        pVar = (ProcessLocalVar *)pGlobal->pFree;//在pFree里獲取
        pVar->pKey = K;
        pVar->pNext = pGlobal->aData[iHash];//插入到hash值是iHash的鏈表中
        pGlobal->aData[iHash] = pVar;//更新頭結點
        pGlobal->nFree -= nByte;
        pGlobal->pFree += nByte;//未使用的空間地址向后移動
        memcpy(&pVar[1], K, L);//得到初始值
      }
    
      return (void *)&pVar[1];// 去除頭部ProcessLocalVar,返回映射地址
    }
    
        最后有一個疑問:既然沒有靜態存儲區,那么pGlobal存在哪里?
    版權聲明:本文為pfysw原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/pfysw/article/details/79398867

    智能推薦

    python類靜態變量

    轉自:https://www.cnblogs.com/Alexzzzz/p/10795227.html 作者:Alexzzzz python的類靜態變量直接定義在類中即可,不需要修飾符,如: 在類Test中,stc_attr是屬于類Test的靜態變量,attr1和attr2是屬于對象的變量。并且通過類名和對象實例訪問stc_attr都是合法的。 可以看到類Test,對象obj1和對象obj2中st...

    kotlin 定義靜態變量

    Kotlin 取消了關鍵字static,也就無法直接聲明靜態成員, 在kotlin中定義靜態變量需要使用伴生類 companion 先看看下java 的定義   如果直接復制粘貼過去如下    但是這些卻不是靜態變量  我們如下寫法即可  為什么要添加注解  官方的語言:在 JVM 平臺,如果使用 @JvmStatic...

    20200719-靜態變量

    輸出結果:...

    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_...

    統計學習方法 - 樸素貝葉斯

    引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...

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