<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ngx_pool_t是一個非常重要的數據結構,在很多重要的場合都有使用,很多重要的數據結構也都在使用它。那么它究竟是一個什么東西呢?簡單的說,它提供了一種機制,幫助管理一系列的資源(如內存,文件等),使得對這些資源的使用和釋放統一進行,免除了使用過程中考慮到對各種各樣資源的什么時候釋放,是否遺漏了釋放的擔心。 例如對于內存的管理,如果我們需要使用內存,那么總是從一個ngx_pool_t的對象中獲取內存,在最終的某個時刻,我們銷毀這個ngx_pool_t對象,所有這些內存都被釋放了。這樣我們就不必要對對這些內存進行malloc和free的操作,不用擔心是否某塊被malloc出來的內存沒有被釋放。因為當ngx_pool_t對象被銷毀的時候,所有從這個對象中分配出來的內存都會被統一釋放掉。 再比如我們要使用一系列的文件,但是我們打開以后,最終需要都關閉,那么我們就把這些文件統一登記到一個ngx_pool_t對象中,當這個ngx_pool_t對象被銷毀的時候,所有這些文件都將會被關閉。 從上面舉的兩個例子中我們可以看出,使用ngx_pool_t這個數據結構的時候,所有的資源的釋放都在這個對象被銷毀的時刻,統一進行了釋放,那么就會帶來一個問題,就是這些資源的生存周期(或者說被占用的時間)是跟ngx_pool_t的生存周期基本一致(ngx_pool_t也提供了少量操作可以提前釋放資源)。從最高效的角度來說,這并不是最好的。比如,我們需要依次使用A,B,C三個資源,且使用完B的時候,A就不會再被使用了,使用C的時候A和B都不會被使用到。如果不使用ngx_pool_t來管理這三個資源,那我們可能從系統里面申請A,使用A,然后在釋放A。接著申請B,使用B,再釋放B。最后申請C,使用C,然后釋放C。但是當我們使用一個ngx_pool_t對象來管理這三個資源的時候,A,B和C的釋放是在最后一起發生的,也就是在使用完C以后。誠然,這在客觀上增加了程序在一段時間的資源使用量。但是這也減輕了程序員分別管理三個資源的生命周期的工作。這也就是有所得,必有所失的道理。實際上是一個取舍的問題,要看在具體的情況下,你更在乎的是哪個。 可以看一下在nginx里面一個典型的使用ngx_pool_t的場景,對于nginx處理的每個http request, nginx會生成一個ngx_pool_t對象與這個http request關聯,所有處理過程中需要申請的資源都從這個ngx_pool_t對象中獲取,當這個http request處理完成以后,所有在處理過程中申請的資源,都將隨著這個關聯的ngx_pool_t對象的銷毀而釋放。 ngx_pool_t相關結構及操作被定義在文件src/core/ngx_palloc.h|c中。 [](http:// "點擊提交Issue,反饋你的意見...") typedef struct ngx_pool_s ngx_pool_t; struct ngx_pool_s { ngx_pool_data_t d; size_t max; ngx_pool_t *current; ngx_chain_t *chain; ngx_pool_large_t *large; ngx_pool_cleanup_t *cleanup; ngx_log_t *log; }; 從ngx_pool_t的一般使用者的角度來說,可不用關注ngx_pool_t結構中各字段作用。所以這里也不會進行詳細的解釋,當然在說明某些操作函數的使用的時候,如有必要,會進行說明。 下面我們來分別解釋下ngx_pool_t的相關操作。 [](http:// "點擊提交Issue,反饋你的意見...") ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log); 創建一個初始節點大小為size的pool,log為后續在該pool上進行操作時輸出日志的對象。 需要說明的是size的選擇,size的大小必須小于等于NGX_MAX_ALLOC_FROM_POOL,且必須大于sizeof(ngx_pool_t)。 選擇大于NGX_MAX_ALLOC_FROM_POOL的值會造成浪費,因為大于該限制的空間不會被用到(只是說在第一個由ngx_pool_t對象管理的內存塊上的內存,后續的分配如果第一個內存塊上的空閑部分已用完,會再分配的)。 選擇小于sizeof(ngx_pool_t)的值會造成程序崩潰。由于初始大小的內存塊中要用一部分來存儲ngx_pool_t這個信息本身。 當一個ngx_pool_t對象被創建以后,該對象的max字段被賦值為size-sizeof(ngx_pool_t)和NGX_MAX_ALLOC_FROM_POOL這兩者中比較小的。后續的從這個pool中分配的內存塊,在第一塊內存使用完成以后,如果要繼續分配的話,就需要繼續從操作系統申請內存。當內存的大小小于等于max字段的時候,則分配新的內存塊,鏈接在d這個字段(實際上是d.next字段)管理的一條鏈表上。當要分配的內存塊是比max大的,那么從系統中申請的內存是被掛接在large字段管理的一條鏈表上。我們暫且把這個稱之為大塊內存鏈和小塊內存鏈。 [](http:// "點擊提交Issue,反饋你的意見...") void *ngx_palloc(ngx_pool_t *pool, size_t size); 從這個pool中分配一塊為size大小的內存。注意,此函數分配的內存的起始地址按照NGX_ALIGNMENT進行了對齊。對齊操作會提高系統處理的速度,但會造成少量內存的浪費。 [](http:// "點擊提交Issue,反饋你的意見...") void *ngx_pnalloc(ngx_pool_t *pool, size_t size); 從這個pool中分配一塊為size大小的內存。但是此函數分配的內存并沒有像上面的函數那樣進行過對齊。 [](http:// "點擊提交Issue,反饋你的意見...") void *ngx_pcalloc(ngx_pool_t *pool, size_t size); 該函數也是分配size大小的內存,并且對分配的內存塊進行了清零。內部實際上是轉調用ngx_palloc實現的。 [](http:// "點擊提交Issue,反饋你的意見...") void *ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment); 按照指定對齊大小alignment來申請一塊大小為size的內存。此處獲取的內存不管大小都將被置于大內存塊鏈中管理。 [](http:// "點擊提交Issue,反饋你的意見...") ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p); 對于被置于大塊內存鏈,也就是被large字段管理的一列內存中的某塊進行釋放。該函數的實現是順序遍歷large管理的大塊內存鏈表。所以效率比較低下。如果在這個鏈表中找到了這塊內存,則釋放,并返回NGX_OK。否則返回NGX_DECLINED。 由于這個操作效率比較低下,除非必要,也就是說這塊內存非常大,確應及時釋放,否則一般不需要調用。反正內存在這個pool被銷毀的時候,總歸會都釋放掉的嘛! [](http:// "點擊提交Issue,反饋你的意見...") ngx_pool_cleanup_t *ngx_pool_cleanup_add(ngx_pool_t *p, size_t size); ngx_pool_t中的cleanup字段管理著一個特殊的鏈表,該鏈表的每一項都記錄著一個特殊的需要釋放的資源。對于這個鏈表中每個節點所包含的資源如何去釋放,是自說明的。這也就提供了非常大的靈活性。意味著,ngx_pool_t不僅僅可以管理內存,通過這個機制,也可以管理任何需要釋放的資源,例如,關閉文件,或者刪除文件等等。下面我們看一下這個鏈表每個節點的類型: [](http:// "點擊提交Issue,反饋你的意見...") typedef struct ngx_pool_cleanup_s ngx_pool_cleanup_t; typedef void (*ngx_pool_cleanup_pt)(void *data); struct ngx_pool_cleanup_s { ngx_pool_cleanup_pt handler; void *data; ngx_pool_cleanup_t *next; }; | data: | 指明了該節點所對應的資源。 | |-----|-----| | handler: | 是一個函數指針,指向一個可以釋放data所對應資源的函數。該函數只有一個參數,就是data。 | | next: | 指向該鏈表中下一個元素。 | 看到這里,ngx_pool_cleanup_add這個函數的用法,我相信大家都應該有一些明白了。但是這個參數size是起什么作用的呢?這個 size就是要存儲這個data字段所指向的資源的大小,該函數會為data分配size大小的空間。 比如我們需要最后刪除一個文件。那我們在調用這個函數的時候,把size指定為存儲文件名的字符串的大小,然后調用這個函數給cleanup鏈表中增加一項。該函數會返回新添加的這個節點。我們然后把這個節點中的data字段拷貝為文件名。把hander字段賦值為一個刪除文件的函數(當然該函數的原型要按照void (*ngx_pool_cleanup_pt)(void *data))。 [](http:// "點擊提交Issue,反饋你的意見...") void ngx_destroy_pool(ngx_pool_t *pool); 該函數就是釋放pool中持有的所有內存,以及依次調用cleanup字段所管理的鏈表中每個元素的handler字段所指向的函數,來釋放掉所有該pool管理的資源。并且把pool指向的ngx_pool_t也釋放掉了,完全不可用了。 [](http:// "點擊提交Issue,反饋你的意見...") void ngx_reset_pool(ngx_pool_t *pool); 該函數釋放pool中所有大塊內存鏈表上的內存,小塊內存鏈上的內存塊都修改為可用。但是不會去處理cleanup鏈表上的項目。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看