婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > nginx中共享內存的使用詳解

nginx中共享內存的使用詳解

熱門標簽:高德地圖標注無營業執照 智能電話機器人線路 賀州市地圖標注app 百度地圖標注要不要錢 江蘇電銷外呼防封系統是什么 廣州電銷機器人系統圖 東莞人工智能電銷機器人供應商 金融行業外呼線路 長沙開福怎么申請400電話

在nginx的進程模型下,類似流量統計、流量控制、數據共享、等需要多個工作進程共同配合完成任務,共享內存是一個重要的進程通訊的方案。本文介紹在nginx的代碼中與共享內存相關的功能,包括ngx_shmem與ngx_slab的使用與注意事項,但不包括ngx_slab中實現的內存管理算法。

ngx_shmem的使用

ngx_shmem.c/h文件只是對mmap()/munmap()系統調用或者shmget()/shmdt()的一個很簡單的封裝。實現了ngx風格的基礎庫,可以申請和釋放一段連續的共享內存空間。一般用于固定長度的共享數據使用,使用過程中數據長度固定不會伸縮。

typedef struct {
  u_char   *addr;
  size_t    size;
  ...
} ngx_shm_t;
ngx_int_t ngx_shm_alloc(ngx_shm_t *shm);
void ngx_shm_free(ngx_shm_t *shm);

在ngxin中共享內存的使用流程,一般是由master進程創建,worker進程通過繼承的方式獲得內存指針。

關于ngx_shmem的使用,可以參考ngx_event_module_init()中部分片段,這部分代碼在共享內存中創建了若干個變量,用于記錄各個狀態(accepted/reading/writing...)的請求數量,并在ngx_event_module中的幾個關鍵事件入口對這幾個變量進行加減統計操作。實現統計所有worker進程當前的請求狀態。

shm.size = size;
ngx_str_set(&shm.name, "nginx_shared_zone");
shm.log = cycle->log;

if (ngx_shm_alloc(&shm) != NGX_OK) {
  return NGX_ERROR;
}

shared = shm.addr;
...
ngx_stat_accepted = (ngx_atomic_t *) (shared + 3 * cl);
ngx_stat_handled = (ngx_atomic_t *) (shared + 4 * cl);
ngx_stat_requests = (ngx_atomic_t *) (shared + 5 * cl);
ngx_stat_active = (ngx_atomic_t *) (shared + 6 * cl);
ngx_stat_reading = (ngx_atomic_t *) (shared + 7 * cl);
ngx_stat_writing = (ngx_atomic_t *) (shared + 8 * cl);
ngx_stat_waiting = (ngx_atomic_t *) (shared + 9 * cl);

關于這個功能的更多細節,可以查看代碼中的NGX_STAT_STUB宏定義相關代碼與ngx_http_stub_status_module。

ngx_slab的使用

ngx_shmem是一層極簡的封裝,實現了共享內存的基本功能。但我們程序中大部分的場景共享數據并不會一個固定大小的結構,而更多是像ngx_array、ngx_list、ngx_queue、ngx_rbtree這類大小可以變化的數據結構。

我們期望能有像ngx_pool_t一樣可以動態申請釋放空間一個內存池。ngx_slab正是一個這樣的結構體,原理上與系統的malloc()有相識之處都是通過一系列算法實現對一段段內存片段的申請與釋放。只不過ngx_slab操作的對象是基于ngx_shmem的共享內存。

先看一下ngx_slab的接口

typedef struct {
  ngx_shmtx_t    mutex;
  ...
  void       *data; /* 一般存放從pool中申請獲得的根數據地址(pool中第一個申請的數據接口) */
  void       *addr; /* 使用ngx_shmem申請獲得的共享內存基地址 */
} ngx_slab_pool_t;

void ngx_slab_init(ngx_slab_pool_t *pool);
void *ngx_slab_alloc(ngx_slab_pool_t *pool, size_t size);
void *ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size);
void *ngx_slab_calloc(ngx_slab_pool_t *pool, size_t size);
void *ngx_slab_calloc_locked(ngx_slab_pool_t *pool, size_t size);
void ngx_slab_free(ngx_slab_pool_t *pool, void *p);
void ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p);

可以看到接口并不復雜,alloc與calloc的區別在于是否對申請獲得的內存段清零,_locked結尾的接口表示操作的pool已經是獲取到鎖的。在ngx_slab_pool_t的結構體有一個ngx_shmtx_t的互斥鎖用于同步多進程同時訪問pool的并發場景。注意ngx_slab_alloc()會先獲取鎖、然后申請空間、最后釋放鎖。而ngx_slab_alloc_locked()則直接申請空間,認為程序已經在其他邏輯中獲得鎖了。

在nginx的開發中使用ngx_shmem一般需要遵循以下初始化流程:

  • 模塊在配置解析過程中調用ngx_shared_memory_add()接口,注冊一段共享內存。提供共享內存大小與內存初始化的回調函數。
  • 框架在ngx_init_cycle()中使用ngx_shmem申請內存,并初始化ngx_slab,然后回調模塊注冊的初始化函數
  • 模塊使用ngx_slab的申請/是否接口

在這個流程中,涉及到ngx_shared_memory_add()接口與對應的ngx_shm_zone_t結構體。

struct ngx_shm_zone_s {
  void           *data;
  ngx_shm_t         shm;
  ngx_shm_zone_init_pt   init;
  void           *tag;
  void           *sync;
  ngx_uint_t        noreuse; /* unsigned noreuse:1; */
};
ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name,
  size_t size, void *tag);

其中值得一提的是noreuse屬性,這個屬性控制了在nginx的reload過程中是否會重新申請共享內存。

由于關于ngx_init_cycle()函數較長,這個流程可以通過查找/* create shared memory */這個注釋或者cycle->shared_memory這個對象查看相關代碼。

關于ngx_slab更多細節的使用,建議可以參考ngx_http_limit_conn_module,這是通過共享內存實現連接數限制的模塊,模塊復雜度底,是一個很好的參考范例。

 參考資料

深入理解Nginx(第2版) https://book.douban.com/subject/26745255/

ngx_http_limit_conn_module http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

標簽:松原 北京 張家界 玉樹 洛陽 滄州 永州 廊坊

巨人網絡通訊聲明:本文標題《nginx中共享內存的使用詳解》,本文關鍵詞  nginx,中,共享,內存,的,使用,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《nginx中共享內存的使用詳解》相關的同類信息!
  • 本頁收集關于nginx中共享內存的使用詳解的相關信息資訊供網民參考!
  • 推薦文章
    主站蜘蛛池模板: 新宁县| 文登市| 上饶县| 嘉义市| 龙山县| 新巴尔虎左旗| 山西省| 霍城县| 嵊州市| 辉南县| 驻马店市| 丘北县| 定兴县| 扎赉特旗| 晋江市| 昌图县| 台南县| 监利县| 高平市| 正宁县| 苏尼特左旗| 怀宁县| 红原县| 东港市| 南康市| 通化市| 绍兴市| 介休市| 江川县| 白银市| 称多县| 衡南县| 高邑县| 陇西县| 乐陵市| 东方市| 新竹市| 灵璧县| 佛冈县| 嵊州市| 达拉特旗|