>  기사  >  백엔드 개발  >  nginx 소스 코드 연구 노트(20) - 이벤트 모듈 1 - 초기화

nginx 소스 코드 연구 노트(20) - 이벤트 모듈 1 - 초기화

WBOY
WBOY원래의
2016-07-29 09:11:01906검색

이전 학습 노트를 읽은 후 nginx의 시작 프로세스에 대해 어느 정도 이해했다고 생각합니다. 이 섹션부터 각 모듈에 대해 자세히 알아보고 각 모듈 내의 주요 작업을 배우고 싶습니다.

이 기사 출처: http://blog.csdn.net/lengzijian/article/details/7598996

오늘 배워봅시다 이벤트 모듈을 다운로드하세요. 이전 시작에서 각 모듈의 후크 함수를 호출하는 것을 여러 번 언급했습니다. 먼저 이벤트 모듈을 시작하는 단계이기도 한 이벤트 모듈의 후크 함수 실행을 떠올려 보겠습니다.

nginx 源码学习笔记(二十)—— event 模块一 ——初始化

1. conf(creat_conf) 생성:

ngx_event_create_conf()

이 방법은 주로 ngx_event_conf_t 구조체를 생성하고 메모리 공간을 할당하는 방법입니다.

2. 구성 파일 읽기:

예를 들어 읽기 파일에는 다음 줄이 있습니다.

[cpp] 보기 일반 카피프린트?

  1. 이벤트 
  2. epoll을 사용하세요.
  3. Worker_connections 10240;
  4. } 로컬 이벤트는 대부분의 명령어를 중괄호 안에 구성할 수 있습니다. /event/ngx_event.c

[cpp] 보기 일반 카피프린트?

정적

ngx_command_t ngx_event_core_commands[] = {
  1. { ngx_string(
  2. "worker_connections"
  3. ),
  4. NGX_EVENT_CONF|NGX_CONF_TAKE1, ngx_event_connections,
  5. 0,
  6. 0,
  7. NULL } ,
  8. ...(생략됨)
  9. { ngx_string(
  10. "연결"
  11. ),
  12. NGX_EVENT_CONF|NGX_CONF_TAKE1, ngx_event_connections,
  13. 0,
  14. 0,
  15. NULL },
  16. { ngx_string(
  17. "사용"
  18. ),
  19. NGX_EVENT_CONF|NGX_CONF_TAKE1, ngx_event_use,
  20. 0,
  21. 0,
  22. NULL },
  23. ngx_null_command
  24. }
  25. 이벤트가 구문 분석되면 다음 함수가 다시 호출됩니다.

[cpp] view 일반 카피프린트?

  1. src/event/ngx_event.c  
  2. 정적  char *  
  3. ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)  
  4. {  
  5.     문자                *rv;  
  6.     무효              ***ctx;  
  7.     ngx_uint_t            i;  
  8.     ngx_conf_t            pcf;  
  9.     ngx_event_module_t   *m;  
  10.   
  11.     /* 이벤트 모듈 수를 계산하고 해당 색인을 설정합니다*/  
  12.     //计算event模块数weight,并且记录  
  13.     ng x_event_max_module = 0 ;  
  14.      (i = 0; ngx_modules[i]; i++) {  
  15. if (ngx_modules[i]->type != NGX_EVENT_MODULE) {  
  16.            계속;  
  17.         }  
  18.   
  19.         ngx_modules[i]->ctx_index = ngx_ event_max_module++ ;  
  20.     }  
  21.   
  22.     ctx = ngx_pcalloc(cf->pool,  sizeof(void *));  
  23.      (ctx == NULL) {  
  24.          반환 NGX_CONF_ERROR;  
  25.     }  
  26.     //为每一个event模块分配空间,用来保存响应配置환상적인 장소  
  27.     //共分配了ngx_event_max_module个空间  
  28.     *ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *));  
  29.     인 경우 (*ctx == NULL) {  
  30.         반환 NGX_CONF_ERROR;  
  31.     }  
  32.   
  33.     *(무효 **) conf = ctx;  
  34.   
  35.      (i = 0; ngx_modules[i]; i++) {
  36.         인 경우 (ngx_modules[i]->type != NGX_EVENT_MODULE) {  
  37.             계속;  
  38.         }
  39. m = ngx_modules[i]->ctx;
  40. //루프에서 각 모듈의 creat_conf 후크 함수를 호출하여 구성 구조를 생성합니다
  41. ->create_conf) { (*ctx)[ngx_modules[i]->ctx_index] = m->create_conf(cf->cycle);
  42. if
  43. ((*ctx)[ngx_modules[i]->ctx_index] == NULL) {                          >                                       
  44. }
  45. pcf = *cf;
  46. cf->ctx = ctx;
  47. cf->module_type = NGX_EVENT_MODULE; F; 블록 명령어 외에도 이벤트 도메인
  48. //예를 들어 앞서 언급한 사용법 등에서 다른 많은 명령어를 구성할 수 있습니다. ., 이제 이벤트 블록의 지침을 구문 분석하고 초기화 작업을 완료합니다.
  49. rv = ngx_conf_parse(cf, NULL)
  50. *cf = pcf;
  51. if (rv != NGX_CONF_OK)
  52. 반품
  53. rv; >
  54. (i = 0; ngx_modules[i]; i++) {
  55. if
  56. (ngx_modules[i]-> != NGX_EVENT_MODULE) {
  57. }                                                        이벤트 모듈의 init_conf 함수는 구성 구조를 초기화합니다.
  58. if (m->init_conf) {
  59. rv = m->init_conf (cf->사이클, (*ctx)[ngx_modules[i]->ctx_index]);
  60.                                                                                                     >
  61.                                                                              > > 반환
  62. NGX_CONF_OK
  63. }

    ngx_events_block() 함수에서 가장 중요한 프로세스는 ngx_conf_parse(cf, NULL)를 호출하는 것입니다. 여기서 ngx_conf_parse()를 호출하는 함수는{} 구성 파일에 있는 모든 구성 지침의 콜백 함수를 호출하여 구성 파일 구문 분석의 초기화를 완료합니다. 그런데 여기서 개인적인 질문이 있어서 선배님들께 물어본 뒤 질문과 답변을 명시하겠습니다******.

    2. 초기화 conf(init_conf)

    ngx_event_init_conf()

    주로 ngx_event_conf_t 구조를 초기화하는 방법입니다.

    3.ngx_event_module_init

    이름으로 보면 모듈의 초기화 작업인 것 같은데 소스를 보면 각 모듈의 코드를 살펴보니 초기화 콜백 함수가 있는 모듈이 없는 것으로 나타났습니다. 저도 왜 여기에 있는지 고민 중인데, 코드를 모두 배운 후에 답을 찾을 수 있기를 바랍니다.

    [cpp] 보기 일반 카피프린트?

  1. src/event/ngx_event.c  
  2. 정적 ngx_int_t  
  3. ngx_event_module_init(ngx_cycle_t *cycle)  
  4. {  
  5.     무효              ***cf;  
  6.     u_char              *공유;  
  7.     size_t               size, cl;  
  8.     ngx_shm_t            shm;  
  9.     ngx_time_t          *tp;  
  10.     ngx_core_conf_t     *ccf;  
  11.     ngx_event_conf_t    *ecf;  
  12.       
  13.     //判断ngx_events_module是否调用过初始화conf操작  
  14.     cf = ngx_get_conf(cycle->conf_ctx, ngx_events_module);  
  15.   
  16.      (cf == NULL) {  
  17.         ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,  
  18.                    "구성에 "이벤트" 섹션이 없음");  
  19.         반환 NGX_ERROR;  
  20.     }  
  21.       
  22.     //获取ngx_event_core_module模끔찍한 흑자结构  
  23.     ecf = (*cf)[ngx_event_core_module.ctx_index];  
  24.       
  25.     //查看是否是event中的模块,例如use 。。。。
  26. if (!ngx_test_config && ngx_process <= NGX_PROCESS_MASTER) { > ngx_log_error (NGX_LOG_NOTICE, 사이클->로그, 0,
  27. 🎜>
  28. , ecf->이름); > }
  29. //ngx_core_module 모듈의 구성 구조 가져오기
  30. ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
  31. // ngx_core_module 모듈의 구성 구조
  32. ngx_timer_solution = ccf-> ;timer_solution;
  33. #if !(NGX_WIN32)
  34. {
  35. ngx_int_t 제한
  36. //현재 프로세스에서 열 수 있는 최대 파일 수를 가져옵니다. getrlimit
  37. if
  38. (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
  39. ngx_log_error(NGX_LOG_ALERT, 사이클->log, ngx_errno,                                             )
  40. }else {
  41. //ngx_event_core_module 모듈 연결 수가 현재(소프트) 제한보다 큰 경우
  42.                                                                                          /또는 ngx_event_core_module 연결 수가 ngx_core_module의 최대 연결 수보다 큽니다
  43. if (ecf->connections > ( ngx_uint_t) rlmt.rlim_cur
  44.                                         || ;연결 > ; (ngx_uint_t) ccf->rlimit_nofile))
  45. {
  46. 제한 = (ccf->rlimit_nofile == NGX_ CONF_UNSET) ?
  47. (ngx_int_t) rlmt.rlim_cur : ccf->rlimit_nofile
  48. ngx_log_error( NGX_LOG_WARN, 사이클->log, 0,
  49.                                     
  50.    > 🎜>                                                            >#endif /* !(NGX_WIN32) */
  51. //마스터 프로세스 종료 후
  52. 으로 돌아가는 경우//마스터 프로세스 종료는 단일 프로세스이므로 작업 모드,
  53. // 작업 후 공유 메모리 구현 잠금 및 기타 작업을 생성합니다. 단일 프로세스가 필요하지 않습니다.
  54. if (ccf->master == 0) {
  55.                                                                    //뮤텍스를 허용하는 경우 이미 존재하므로 다시 생성할 필요가 없습니다.
  56. if
  57. (ngx_accept_mutex_ptr) {
  58. return
  59. NGX_OK; >
  60. }
  61. /* cl은 캐시 라인 크기와 같거나 커야 합니다. */
  62. cl = 128;
  63. //여기서 크기별 공유 메모리를 생성합니다.
  64. 크기 = cl
  65. /* ngx_accept_mutex */
  66. + cl / * ngx_connection_counter * /
  67.     +cl;   /* ngx_temp_number */
  68. //공유 메모리 준비, 크기는 nginx_shared_zone,
  69. shm.size = 크기; 🎜>
  70. shm.name.data = (u_char *)
  71. "nginx_shared_zone"
  72. ; shm.log = 사이클->로그
  73. shm.addr
  74. if (ngx_shm_alloc(&shm) != NGX_OK) {                                                                                              🎜>//시작 주소를 얻어서 저장하세요
  75. 공유 = shm.addr
  76. //accept mutex는 공유 메모리의 첫 번째 cl 크기 메모리를 가져옵니다
  77. ngx_accept_mutex_ptr = (ngx_atomic_t *)
  78. ngx_accept_mutex.spin = (ngx_uint_t) -1; /*상호작용 허용 제외 생성
  79. accept mutex의 구현은 원자 연산을 지원하는지 여부에 따라 다릅니다.
  80. 얻은 값은 accept 뮤텍스를 구현하는 데 사용됩니다. 그렇지 않으면 파일 잠금이
  81. 사용되어 accept 뮤텍스를 구현합니다.
  82. Accept 뮤텍스의 기능은 패닉 그룹을 방지하고 워커를 구현하는 것입니다. 프로세스 로드 밸런싱.
  83. */
  84. if (ngx_shmtx_create(&ngx_accept_mutex, shared, Cycle->lock_file.data)
  85. ! = NGX_OK)
  86. {
  87. 🎜> } >
  88. ngx_connection_counter = (ngx_atomic_t *) (shared + 1 * cl)
  89. (void) ngx_atomic_cmp_set(ngx_connection_counter, 0, 1);
  90. ngx_log_debug2( NGX_LOG_DEBUG_EVENT, 사이클->로그, 0,
  91. "카운터: %p, %d",
  92. ngx_connection_counter, *ngx_connection_counter); 🎜>
  93. ngx_temp_number = (ngx_atomic_t *) (공유 + 2 * cl)
  94. tp = ngx_timeofday() 🎜>
  95. 반환 NGX_OK }
  96. 4.ngx_event_process_init
  97. 이 이전 작업자 프로세스 분석에서 언급되었습니다. 작업자 프로세스를 생성한 후 작업자 프로세스는 먼저 프로세스를 초기화하며 이때 ngx_event_process_init 함수가 호출됩니다.
  98. [cpp] 보기 일반 카피프린트?
    1. src/event/ngx_event.c
    2. 정적ngx_int_t >
    3. ngx_event_process_init(ngx_cycle_t *cycle)
    4. {
    5. ngx_uint_t m, i
    6. ngx_event_t *rev, *wev;
    7. ngx_listening_t *ls
    8. ngx_connection_t *c, *next, *old; >
    9. ngx_core_conf_t *ccf; ngx_event_module_t *module ;
    10. //전과 마찬가지로 응답 모듈의 구성 구조 가져오기
    11. ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module)
    12. ecf = ngx_event_get_conf(cycle-&g t;conf_ctx, ngx_event_core_module)
    13. >
    14. //수락 뮤텍스를 엽니다.
    15. if (ccf->master && ccf->worker_processes > 1 && ecf->accept_mutex) {
    16. ngx_use_accept_mutex = 1 // 뮤텍스 사용
    17. ngx_accept_mutex_held = 0 //뮤텍스 승인 여부
    18. ngx_accept_mutex_delay = ecf->accept_mutex_delay;//뮤텍스 경합 실패 후 다음 경합 간격을 기다립니다.
    19. } else
    20. { ngx_use_accept_mutex = 0
    21. } (NGX_THREADS)
    22. //지금은 스레드 이야기는 하지 마세요 >
    23. #endif
    24. 타이머를 유지하는 레드-블랙 트리, 자세히 설명하겠습니다. 나중에
    25. if (ngx_event_timer_init(cycle- >log) == NGX_ERROR) {
    26.                                 > }  
    27.  (m = 0;ngx_모듈[m] ; m++) { 
    28. //앞서 언급했듯이 NGX_EVENT_MODULE 모듈이 아닌 모듈은 건너뜁니다.
    29. if
    30. (ngx_modules[m]->type != NGX_EVENT_MODULE) {  
    31. 계속
    32. ; }
    33.  //사용하지 않는 구성 지시문으로 지정된 모듈은 건너뛰고 Linux는 기본적으로 epoll을 사용합니다
    34.                                                                                       > 🎜> } ]->ctx;
    35.                                                 >
    36. nginx는 epoll, poll, select, dqueue, aio와 같은 많은 이벤트 모듈을 구현하기 때문입니다.
    37. (이러한 모듈은 다음 위치에 있습니다. src/event/modules 디렉터리에 있음), 따라서 nginx는 시간 모듈
    38. 을 추상화하여 다양한 시스템을 용이하게 합니다. 다양한 이벤트 모델을 사용하면 새로운 시간의 확장도 촉진됩니다. 우리의 초점은 epoll에 맞춰져야 합니다.
    39. 여기서 init 콜백은 실제로 ngx_epoll_init 함수를 호출합니다. 모듈->액션 구조는 epoll의 모든 인터페이스 기능을 캡슐화합니다. nginx는 액션 구조를 통해 이벤트 추상화 계층에 epoll을 등록합니다.
    40. 액션 유형은 ngx_event_action_t이며, src/event/ngx_event.h에 위치합니다
    41. 구체적인 내용은 다음 섹션에서 설명하겠습니다.
    42.  
    43. if (module->actions.init(cycle, ngx_timer_solution) != NGX_OK) {
    44.                                                                                       }  
    45.  
    46.                                                                      
    47. //여기에 일부 내용 생략
    48. //전역 생성 ngx_connection_t 배열은 모든 연결을 저장합니다.
    49. //이 프로세스는 각 작업자 프로세스에서 실행되므로 각 작업자는 고유한 연결 배열을 갖습니다.
    50. 사이클->connections =
    51. ngx_alloc(
    52. sizeof(ngx_connection_t) * 사이클 ->connection_n, 사이클->로그)
    53. if ( 사이클->연결 == NULL) {
    54.                                        🎜> } 
    55.  
    56. c = 주기->연결;
    57.  
    58. //읽기 이벤트 배열 생성
    59. 사이클->read_events = ngx_alloc(sizeof(ngx_event_t) * 사이클->connection_n,
    60.          사이클 -> ;log);   🎜> if
    61. (cycle->read_events == NULL) {
    62. 반환
    63. NGX_ERROR
    64. }
    65. rev = Cycle->read_events;
    66.  for (i = 0; i
    67. rev[i].closed = 1
    68. rev[i].instance = 1; >#if(NGX_THREADS)
    69. rev[i].lock = &c[i].lock rev [i].own_lock = &c[i].lock
    70. #endif
    71. > }  
    72.     //创建一个写事件数组  
    73.     cycle->write_events = ngx _alloc (크기(ngx_event_t) * cycle->connection_n,  
    74.                                           주기->log);  
    75.     인 경우 (cycle->write_events == NULL) {  
    76.         반환 NGX_ERROR;  
    77.     }  
    78.   
    79.     wev = cycle->write_events;  
    80.      (i = 0; i < cycle->connection_n; i++) {  
    81.         wev[i].closed = 1;  
    82. #if (NGX_THREADS)  
    83.         wev[i].lock = &c[ i].잠금;  
    84.         wev[i].own_lock = &c[i].lock;  
    85. #endif  
    86.     }  
    87.   
    88.     i = cycle->connection_n;  
    89.     다음 = NULL;  
    90.     //初始化整个connection数组  
    91.     하세요 {  
    92.         i--;  
    93.   
    94.         c[i].data = 다음;  
    95.         c[i].read = &cycle->read_events[i];  
    96.         c[i].write = &cycle->write_events[i];  
    97.         c[i].fd = (ngx_socket_t) -1;  
    98.   
    99.         다음 = &c[i];  
    100.   
    101. #if (NGX_THREADS)  
    102.         c[i].lock = 0;  
    103. #endif  
    104.     }동안 (i)
    105. 🎜>
    106. cycle->free_connection_n =cycle-> Connection_n
    107. /* 각 청취 소켓에 대해 */
    108. //각 청취 소켓, 즉 A 슬롯에 대해 연결 배열에서 연결 할당
    109. ls = 사이클->listening.elts;
    110. for
    111. (i = 0; i //connection solt에서 새 제품 받기
    112. c = ngx_get_connection(ls[i].fd, 사이클->log)
    113.  
    114.  if
    115. (c == NULL) { 
    116.               >반환 NGX_ERROR
    117. }
    118. c->log = &ls[i].log
    119. c->listening =
    120. ls[i].connection =
    121.  
    122. rev = c->read;
    123. ->log = c->log; >
    124. rev->accept = 1; //읽기 시간 발생, 호출 수락
    125. #if (NGX_HAVE_DEFERRED_ACCEPT)
    126.                                                                                >
    127. if (!(ngx_event_flags & NGX_USE_IOC
    128. P_EVENT)) {
    129.  if
    130. (ls[i].previous) {
    131.                             > > * 이전 주기 읽기 이벤트 배열
    132. */
    133. old = ls[i].previous->connection;
    134. if
    135. (ngx_del_event(이전-& gt; 읽기, ngx_read_event, ngx_close_event)
    136. == ngx_error)
    137.                                                                                          
    138. old->fd = (ngx_socket_t ) -1;
    139.                                    🎜>
    140. }
    141. //소켓 중독 이벤트를 수신하는 콜백 함수 등록 ngx_event_accept
    142. rev->handler = ngx_event_accept;
    143. /accept_mutex 사용, 당분간 epoll에 리스닝 소켓을 넣지 않지만
    144. //작업자가 accept mutex를 잡을 때까지 기다린 다음 공황 발작을 피하기 위해 epoll을 삽입합니다.
    145. if
    146. (ngx_use_accept_mutex) { 🎜>
    147.                                 > 🎜>  
    148. if
    149. (ngx_event_flags & NGX_USE_RTSIG_EVENT) {                 
    150. ngx_error;  
    151.                                                        
    152.                                                                                  🎜>
    153. 🎜>
    154. #endif > }
    155. 반환
    156. NGX_OK
    157. }
    158. 현재까지 이벤트 기반 초기화가 완료되었습니다.
    159. 위 내용은 IOC와 카운터 내용을 포함한 nginx 소스코드 연구 노트(20) - 이벤트 모듈 1 - 초기화를 소개하고 있어 PHP 튜토리얼에 관심이 있는 친구들에게 도움이 되길 바랍니다.
성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.