Nginx 의 epoll 이벤트 구동 모듈
27137 단어 nginxepoll비동기 IOepoll 이벤트 구동 모듈
앞의 글 에서 'Nginx 이벤트 모듈' 은 Nginx 의 이벤트 구동 프레임 워 크 와 서로 다른 유형의 이벤트 구동 모듈 의 관 리 를 소개 했다.이 절 은 앞의 지식 을 바탕 으로 Linux 시스템 에서 의 epoll 이벤트 구동 모듈 을 간단하게 소개 합 니 다.epoll 의 사용 과 원 리 는 문장 'epoll 해석' 을 참조 할 수 있 습 니 다.Nginx 서버 가 이벤트 구동 프레임 워 크 를 기반 으로 한 epoll 이벤트 구동 모듈 을 직접 소개 합 니 다.
ngx_epoll_모듈 이벤트 구동 모듈
ngx_epoll_conf_t 구조 체
ngx_epoll_conf_t 구조 체 는 ngx 저장epoll_module 이벤트 구동 모듈 의 설정 항목 구조.이 구조 체 는 파일 src / event / modules / ngx 에 있 습 니 다.epoll_module. c 에서 정의:
/* epoll */
typedef struct {
ngx_uint_t events; /* epoll_wait */
ngx_uint_t aio_requests; /* IO */
} ngx_epoll_conf_t;
ngx_epoll_module 이벤트 구동 모듈 의 정의
모든 모듈 의 정 의 는 모듈 유 니 버 설 인터페이스 ngx 기반 입 니 다.module_t 구조, ngxepoll_module 모듈 은 파일 src / event / modules / ngx 에 있 습 니 다.epoll_module. c 에서 다음 과 같이 정의 합 니 다.
/* epoll */
ngx_module_t ngx_epoll_module = {
NGX_MODULE_V1,
&ngx_epoll_module_ctx, /* module context */
ngx_epoll_commands, /* module directives */
NGX_EVENT_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
재 ngxepoll_module 모듈 의 정의 에서 이 모듈 이 관심 있 는 설정 항목 ngx 를 정의 합 니 다.epoll_commands 배열, 이 설정 항목 배열 은 파일 src / event / modules / ngx 에 있 습 니 다.epoll_module. c 에서 정의:
/* epoll */
static ngx_command_t ngx_epoll_commands[] = {
/*
* epoll_events epoll_wait ( 3 ),
* ngx_epoll_init epoll_events epoll_event ;
*/
{ ngx_string("epoll_events"),
NGX_EVENT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
0,
offsetof(ngx_epoll_conf_t, events),
NULL },
/*
* IO IO ,
* io_setup ;
*/
{ ngx_string("worker_aio_requests"),
NGX_EVENT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
0,
offsetof(ngx_epoll_conf_t, aio_requests),
NULL },
ngx_null_command
};
재 ngxepoll_module 모듈 의 정의 에서 이 모듈 의 문맥 구조 ngx 를 정의 합 니 다.epoll_module_ctx, 이 상하 문 구 조 는 이벤트 모듈 을 바탕 으로 하 는 유 니 버 설 인터페이스 ngxevent_module_t 구조 로 정의 되 었 습 니 다.이 컨 텍스트 구 조 는 파일 src / event / modules / ngx 에 있 습 니 다.epoll_module. c 에서 정의:
/* ngx_event_module_t epoll */
ngx_event_module_t ngx_epoll_module_ctx = {
&epoll_name,
ngx_epoll_create_conf, /* create configuration */
ngx_epoll_init_conf, /* init configuration */
{
ngx_epoll_add_event, /* add an event */
ngx_epoll_del_event, /* delete an event */
ngx_epoll_add_event, /* enable an event */
ngx_epoll_del_event, /* disable an event */
ngx_epoll_add_connection, /* add an connection */
ngx_epoll_del_connection, /* delete an connection */
NULL, /* process the changes */
ngx_epoll_process_events, /* process the events */
ngx_epoll_init, /* init the events */
ngx_epoll_done, /* done the events */
}
};
재 ngxepoll_module 모듈 의 컨 텍스트 이벤트 인터페이스 구조 에서 ngx 를 중점적으로 정의 하 였 습 니 다.event_actions_t 구조 중의 인터페이스 리 셋 방법.
ngx_epoll_module 이벤트 구동 모듈 의 조작
ngx_epoll_module 모듈 의 조작 은 ngxepoll_module 모듈 의 컨 텍스트 이벤트 인터페이스 구조 에서 구성원 actions 가 구현 되 었 습 니 다.이 멤버 가 실현 하 는 방법 은 다음 과 같다.
ngx_epoll_add_event, /* add an event */
ngx_epoll_del_event, /* delete an event */
ngx_epoll_add_event, /* enable an event */
ngx_epoll_del_event, /* disable an event */
ngx_epoll_add_connection, /* add an connection */
ngx_epoll_del_connection, /* delete an connection */
NULL, /* process the changes */
ngx_epoll_process_events, /* process the events */
ngx_epoll_init, /* init the events */
ngx_epoll_done, /* done the events */
ngx_epoll_모듈 초기 화
ngx_epoll_module 모듈 의 초기 화 는 함수 ngxepoll_init 구현.이 함 수 는 주로 두 가지 일 을 했 습 니 다: epoll 대상 을 만 들 고 이벤트 만 들 기list 배열 (epoll wait 함 수 를 호출 할 때 커 널 에서 복 제 된 이벤트 저장 에 사용);이 함 수 는 파일 src / event / modules / ngx 에 있 습 니 다.epoll_module. c 에서 정의:
static int ep = -1; /* epoll */
static struct epoll_event *event_list; /* epoll_wait , */
static ngx_uint_t nevents; /* epoll_wait */
/* epoll */
static ngx_int_t
ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
{
ngx_epoll_conf_t *epcf;
/* ngx_epoll_module */
epcf = ngx_event_get_conf(cycle->conf_ctx, ngx_epoll_module);
if (ep == -1) {
/* epoll_create epoll */
ep = epoll_create(cycle->connection_n / 2);
/* , */
if (ep == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
"epoll_create() failed");
return NGX_ERROR;
}
#if (NGX_HAVE_FILE_AIO)
/* IO, IO */
ngx_epoll_aio_init(cycle, epcf);
#endif
}
/*
* events epoll_event event_list,event_list ;
* events epoll_events ;
*/
if (nevents < epcf->events) {
/*
* event_list epcf->events,
* , ;
*/
if (event_list) {
ngx_free(event_list);
}
/* epcf->events epoll_event , event_list */
event_list = ngx_alloc(sizeof(struct epoll_event) * epcf->events,
cycle->log);
if (event_list == NULL) {
return NGX_ERROR;
}
}
/* epoll_event */
nevents = epcf->events;
/* IO */
/*
* ngx_io, ngx_os_io :
ngx_os_io_t ngx_os_io = {
ngx_unix_recv,
ngx_readv_chain,
ngx_udp_unix_recv,
ngx_unix_send,
ngx_writev_chain,
0
};( src/os/unix/ngx_posix_init.c)
*/
ngx_io = ngx_os_io;
/* ngx_event_actions */
ngx_event_actions = ngx_epoll_module_ctx.actions;
#if (NGX_HAVE_CLEAR_EVENT)
/* ET */
ngx_event_flags = NGX_USE_CLEAR_EVENT
#else
/* LT */
ngx_event_flags = NGX_USE_LEVEL_EVENT
#endif
|NGX_USE_GREEDY_EVENT
|NGX_USE_EPOLL_EVENT;
return NGX_OK;
}
ngx_epoll_module 모듈 의 이벤트 처리
ngx_epoll_module 모듈 의 이벤트 처 리 는 함수 ngxepoll_process_이벤트 구현.ngx_epoll_process_이벤트 함 수 는 이벤트 수집, 이벤트 발송 을 실현 하 는 인터페이스 입 니 다.이 함 수 는 파일 src / event / modules / ngx 에 있 습 니 다.epoll_module. c 에서 정의:
/* */
static ngx_int_t
ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
{
int events;
uint32_t revents;
ngx_int_t instance, i;
ngx_uint_t level;
ngx_err_t err;
ngx_event_t *rev, *wev, **queue;
ngx_connection_t *c;
/* NGX_TIMER_INFINITE == INFTIM */
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"epoll timer: %M", timer);
/* epoll_wait timer */
events = epoll_wait(ep, event_list, (int) nevents, timer);
/* , */
err = (events == -1) ? ngx_errno : 0;
/*
* timer_resolution ,
* NGX_UPDATE_TIME epoll_wait ;
* timer_resolution ,
* timer_resolution ngx_event_timer_alarm 1, ;
*/
if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
/* , , */
ngx_time_update();
}
/* epoll_wait */
if (err) {
if (err == NGX_EINTR) {
if (ngx_event_timer_alarm) {
ngx_event_timer_alarm = 0;
return NGX_OK;
}
level = NGX_LOG_INFO;
} else {
level = NGX_LOG_ALERT;
}
ngx_log_error(level, cycle->log, err, "epoll_wait() failed");
return NGX_ERROR;
}
/*
* epoll_wait events 0, :
* 1、 , timer;
* 2、 timer , error ;
*/
if (events == 0) {
if (timer != NGX_TIMER_INFINITE) {
return NGX_OK;
}
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
"epoll_wait() returned no events without timeout");
return NGX_ERROR;
}
/* */
ngx_mutex_lock(ngx_posted_events_mutex);
/* epoll_wait , */
for (i = 0; i < events; i++) {
/*
* ;
* ;
*/
c = event_list[i].data.ptr;
/* , */
instance = (uintptr_t) c & 1;
/* , */
c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1);
/* */
rev = c->read;
/*
* instance ;
* fd -1, instance , ;
*/
if (c->fd == -1 || rev->instance != instance) {
/*
* the stale event from a file descriptor
* that was just closed in this iteration
*/
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"epoll: stale event %p", c);
continue;
}
/* */
revents = event_list[i].events;
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"epoll: fd:%d ev:%04XD d:%p",
c->fd, revents, event_list[i].data.ptr);
/* epoll_wait */
/*
* EPOLLERR ;EPOLLHUP RST ;
* ,TCP ;
*/
if (revents & (EPOLLERR|EPOLLHUP)) {
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"epoll_wait() error on fd:%d ev:%04XD",
c->fd, revents);
}
#if 0
if (revents & ~(EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP)) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
"strange epoll_wait() events fd:%d ev:%04XD",
c->fd, revents);
}
#endif
/*
* EPOLLIN、EPOLLOUT,
* EPOLLIN、EPOLLOUT revents ;
* ;
*/
if ((revents & (EPOLLERR|EPOLLHUP))
&& (revents & (EPOLLIN|EPOLLOUT)) == 0)
{
/*
* if the error events were returned without EPOLLIN or EPOLLOUT,
* then add these flags to handle the events at least in one
* active handler
*/
revents |= EPOLLIN|EPOLLOUT;
}
/* , active */
if ((revents & EPOLLIN) && rev->active) {
#if (NGX_HAVE_EPOLLRDHUP)
/* EPOLLRDHUP */
if (revents & EPOLLRDHUP) {
rev->pending_eof = 1;
}
#endif
if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) {
rev->posted_ready = 1;
} else {
/* */
/*
* active ready:
* active epoll ,
* ready , IO ;
*/
rev->ready = 1;
}
/*
* NGX_POST_EVENTS ,
* accept ;
*/
if (flags & NGX_POST_EVENTS) {
queue = (ngx_event_t **) (rev->accept ?
&ngx_posted_accept_events : &ngx_posted_events);
ngx_locked_post_event(rev, queue);
} else {
/* , */
rev->handler(rev);
}
}
/* , */
wev = c->write;
/* , active */
if ((revents & EPOLLOUT) && wev->active) {
/* */
if (c->fd == -1 || wev->instance != instance) {
/*
* the stale event from a file descriptor
* that was just closed in this iteration
*/
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"epoll: stale event %p", c);
continue;
}
if (flags & NGX_POST_THREAD_EVENTS) {
wev->posted_ready = 1;
} else {
/* */
wev->ready = 1;
}
/*
* NGX_POST_EVENTS ,
* accept ;
*/
if (flags & NGX_POST_EVENTS) {
ngx_locked_post_event(wev, &ngx_posted_events);
} else {
/* , */
wev->handler(wev);
}
}
}
ngx_mutex_unlock(ngx_posted_events_mutex);
return NGX_OK;
}
ngx_epoll_module 모듈 의 이벤트 추가 및 삭제
ngx_epoll_module 모듈 의 이벤트 추가 와 삭 제 는 각각 함수 ngxepoll_add_이벤트 와 ngxepoll_del_이벤트 구현.이 두 함수 의 실현 은 모두 epoll 호출 을 통 해 이 루어 집 니 다.ctl 함수.구체 적 으로 파일 src / event / modules / ngxepoll_module. c 에서 정의:
/* epoll */
static ngx_int_t
ngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
{
int op;
uint32_t events, prev;
ngx_event_t *e;
ngx_connection_t *c;
struct epoll_event ee;
/* data ngx_connection_t */
/* */
c = ev->data;
/* events */
events = (uint32_t) event;
/*
* , active ;
* epoll_ctl add mod ,
* epoll , ;
* epoll , epoll ;
* epoll ;
*/
if (event == NGX_READ_EVENT) {
/*
* event ;
* epoll ,
* ;
*/
e = c->write;
prev = EPOLLOUT;
#if (NGX_READ_EVENT != EPOLLIN|EPOLLRDHUP)
events = EPOLLIN|EPOLLRDHUP;
#endif
} else {
e = c->read;
prev = EPOLLIN|EPOLLRDHUP;
#if (NGX_WRITE_EVENT != EPOLLOUT)
events = EPOLLOUT;
#endif
}
/* active , */
if (e->active) {
/* , */
op = EPOLL_CTL_MOD;
events |= prev;
} else {
/* , epoll */
op = EPOLL_CTL_ADD;
}
/* flags events */
ee.events = events | (uint32_t) flags;
/* prt ngx_connection_t instance */
ee.data.ptr = (void *) ((uintptr_t) c | ev->instance);
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
"epoll add event: fd:%d op:%d ev:%08XD",
c->fd, op, ee.events);
/* epoll_ctl epoll epoll */
if (epoll_ctl(ep, op, c->fd, &ee) == -1) {
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
"epoll_ctl(%d, %d) failed", op, c->fd);
return NGX_ERROR;
}
/* active 1, */
ev->active = 1;
#if 0
ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1 : 0;
#endif
return NGX_OK;
}
/* epoll */
static ngx_int_t
ngx_epoll_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
{
int op;
uint32_t prev;
ngx_event_t *e;
ngx_connection_t *c;
struct epoll_event ee;
/*
* when the file descriptor is closed, the epoll automatically deletes
* it from its queue, so we do not need to delete explicitly the event
* before the closing the file descriptor
*/
/* ,epoll */
if (flags & NGX_CLOSE_EVENT) {
ev->active = 0;
return NGX_OK;
}
/* */
c = ev->data;
/* event */
if (event == NGX_READ_EVENT) {
/* , active */
e = c->write;
prev = EPOLLOUT;
} else {
/* , active */
e = c->read;
prev = EPOLLIN|EPOLLRDHUP;
}
/*
* , , ;
* , , ;
*/
if (e->active) {
op = EPOLL_CTL_MOD;
ee.events = prev | (uint32_t) flags;
ee.data.ptr = (void *) ((uintptr_t) c | ev->instance);
} else {
/* , , */
op = EPOLL_CTL_DEL;
ee.events = 0;
ee.data.ptr = NULL;
}
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
"epoll del event: fd:%d op:%d ev:%08XD",
c->fd, op, ee.events);
/* */
if (epoll_ctl(ep, op, c->fd, &ee) == -1) {
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
"epoll_ctl(%d, %d) failed", op, c->fd);
return NGX_ERROR;
}
/* active */
ev->active = 0;
return NGX_OK;
}
ngx_epoll_module 모듈 의 연결 추가 및 삭제
ngx_epoll_module 모듈 의 연결 추가 와 삭 제 는 각각 함수 ngxepoll_add_connection 과 ngxepoll_del_connection 실현.이 두 함수 의 실현 은 모두 epoll 호출 을 통 해 이 루어 집 니 다.ctl 함수.구체 적 으로 파일 src / event / modules / ngxepoll_module. c 에서 정의:
/* epoll */
static ngx_int_t
ngx_epoll_add_connection(ngx_connection_t *c)
{
struct epoll_event ee;
/* : 、 、ET */
ee.events = EPOLLIN|EPOLLOUT|EPOLLET|EPOLLRDHUP;
ee.data.ptr = (void *) ((uintptr_t) c | c->read->instance);
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
"epoll add connection: fd:%d ev:%08XD", c->fd, ee.events);
/* epoll_ctl epoll */
if (epoll_ctl(ep, EPOLL_CTL_ADD, c->fd, &ee) == -1) {
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
"epoll_ctl(EPOLL_CTL_ADD, %d) failed", c->fd);
return NGX_ERROR;
}
/* active */
c->read->active = 1;
c->write->active = 1;
return NGX_OK;
}
Nginx
/* epoll */
static ngx_int_t
ngx_epoll_del_connection(ngx_connection_t *c, ngx_uint_t flags)
{
int op;
struct epoll_event ee;
/*
* when the file descriptor is closed the epoll automatically deletes
* it from its queue so we do not need to delete explicitly the event
* before the closing the file descriptor
*/
if (flags & NGX_CLOSE_EVENT) {
c->read->active = 0;
c->write->active = 0;
return NGX_OK;
}
ngx_log_debug1(NGX_LOG_DEBUG_EVENTNginx, c->log, 0,
"epoll del connection: fd:%d", c->fd);
op = EPOLL_CTL_DEL;
ee.events = 0;
ee.data.ptr = NULL;
/* epoll_ctl epoll */
if (epoll_ctl(ep, op, c->fd, &ee) == -1) {
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
"epoll_ctl(%d, %d) failed", op, c->fd);
return NGX_ERROR;
}
/* active */
c->read->active = 0;
c->write->active = 0;
return NGX_OK;
}
ngx_epoll_module 모듈 의 비동기 I / O
Nginx 에서 파일 비동기 I / O 이벤트 가 끝 난 후 알림 은 epoll 대상 에 통합 되 었 습 니 다.이 모듈 의 파일 비동기 I / O 는 다음 과 같 습 니 다.
#if (NGX_HAVE_FILE_AIO)
int ngx_eventfd = -1; /* IO */
aio_context_t ngx_aio_ctx = 0; /* IO , io_setup */
static ngx_event_t ngx_eventfd_event; /* IO */
static ngx_connection_t ngx_eventfd_conn; /* IO ngx_connection_t */
#endif
#if (NGX_HAVE_FILE_AIO)
/*
* We call io_setup(), io_destroy() io_submit(), and io_getevents() directly
* as syscalls instead of libaio usage, because the library header file
* supports eventfd() since 0.3.107 version only.
*
* Also we do not use eventfd() in glibc, because glibc supports it
* since 2.8 version and glibc maps two syscalls eventfd() and eventfd2()
* into single eventfd() function with different number of parameters.
*/
/* IO */
static int
io_setup(u_int nr_reqs, aio_context_t *ctx)
{
return syscall(SYS_io_setup, nr_reqs, ctx);
}
/* IO */
static int
io_destroy(aio_context_t ctx)
{
return syscall(SYS_io_destroy, ctx);
}
/* IO */
static int
io_getevents(aio_context_t ctx, long min_nr, long nr, struct io_event *events,
struct timespec *tmo)
{
return syscall(SYS_io_getevents, ctx, min_nr, nr, events, tmo);
}
/* IO */
static void
ngx_epoll_aio_init(ngx_cycle_t *cycle, ngx_epoll_conf_t *epcf)
{
int n;
struct epoll_event ee;
/* Linux */
ngx_eventfd = syscall(SYS_eventfd, 0);
if (ngx_eventfd == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
"eventfd() failed");
ngx_file_aio = 0;
return;
}
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"eventfd: %d", ngx_eventfd);
n = 1;
/* ngx_eventfd IO */
if (ioctl(ngx_eventfd, FIONBIO, &n) == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
"ioctl(eventfd, FIONBIO) failed");
goto failed;
}
/* IO */
if (io_setup(epcf->aio_requests, &ngx_aio_ctx) == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
"io_setup() failed");
goto failed;
}
/* IO ngx_eventfd_event, ngx_eventfd ngx_event */
/* IO ngx_eventfd_event , ngx_eventfd_conn */
ngx_eventfd_event.data = &ngx_eventfd_conn;
/* IO , ngx_epoll_eventfd_handler */
ngx_eventfd_event.handler = ngx_epoll_eventfd_handler;
/* */
ngx_eventfd_event.log = cycle->log;
/* active */
ngx_eventfd_event.active = 1;
/* ngx_eventfd_conn */
ngx_eventfd_conn.fd = ngx_eventfd;
/* ngx_eventfd_conn ngx_eventfd_event */
ngx_eventfd_conn.read = &ngx_eventfd_event;
/* */
ngx_eventfd_conn.log = cycle->log;
ee.events = EPOLLIN|EPOLLET;
ee.data.ptr = &ngx_eventfd_conn;
/* epoll IO ngx_eventfd */
if (epoll_ctl(ep, EPOLL_CTL_ADD, ngx_eventfd, &ee) != -1) {
return;
}
/* , IO , */
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
"epoll_ctl(EPOLL_CTL_ADD, eventfd) failed");
if (io_destroy(ngx_aio_ctx) == -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"io_destroy() failed");
}
failed:
if (close(ngx_eventfd) == -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"eventfd close() failed");
}
ngx_eventfd = -1;
ngx_aio_ctx = 0;
ngx_file_aio = 0;
}
#endif
#if (NGX_HAVE_FILE_AIO)
/* IO */
static void
ngx_epoll_eventfd_handler(ngx_event_t *ev)
{
int n, events;
long i;
uint64_t ready;
ngx_err_t err;
ngx_event_t *e;
ngx_event_aio_t *aio;
struct io_event event[64]; /* 64 */
struct timespec ts;
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "eventfd handler");
/* , ready */
n = read(ngx_eventfd, &ready, 8);
err = ngx_errno;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0, "eventfd: %d", n);
if (n != 8) {
if (n == -1) {
if (err == NGX_EAGAIN) {
return;
}
ngx_log_error(NGX_LOG_ALERT, ev->log, err, "read(eventfd) failed");
return;
}
ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
"read(eventfd) returned only %d bytes", n);
return;
}
ts.tv_sec = 0;
ts.tv_nsec = 0;
/* ready, IO */
while (ready) {
/* IO */
events = io_getevents(ngx_aio_ctx, 1, 64, event, &ts);
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
"io_getevents: %l", events);
if (events > 0) {
ready -= events;/* ready */
/* */
for (i = 0; i < events; i++) {
ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ev->log, 0,
"io_event: %uXL %uXL %L %L",
event[i].data, event[i].obj,
event[i].res, event[i].res2);
/* IO */
e = (ngx_event_t *) (uintptr_t) event[i].data;
e->complete = 1;
e->active = 0;
e->ready = 1;
aio = e->data;
aio->res = event[i].res;
/* ngx_posted_event */
ngx_post_event(e, &ngx_posted_events);
}
continue;
}
if (events == 0) {
return;
}
/* events == -1 */
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
"io_getevents() failed");
return;
}
}
#endif
참고 자료:
& lt; Nginx 깊이 이해 & gt;
《 모듈 ngx epoll module 상세 해 》
《 nginx epoll 상세 해 》.
《 Nginx 소스 코드 분석 - Epol 모듈 》
< ngx epoll add event 에 대한 설명 >
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
간단! Certbot을 사용하여 웹 사이트를 SSL(HTTPS)화하는 방법초보자가 인프라 주위를 정돈하는 것은 매우 어렵습니다. 이번은 사이트를 간단하게 SSL화(HTTP에서 HTTPS통신)로 변경하는 방법을 소개합니다! 이번에는 소프트웨어 시스템 Nginx CentOS7 의 환경에서 S...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.