nginx/nginx
Architecture
NGINX is a single C program built around three ideas: a module-based design where every feature is an ngx_module_t; a non-blocking, event-driven I/O loop where one OS thread per worker handles thousands of connections; and a master/worker process model that gives each worker its own pre-allocated pool of connections and shares state through mmap'd memory zones.
Process model
graph TD
M[master process<br/>nginx -g] -->|fork + exec| W1[worker 0]
M -->|fork + exec| W2[worker 1]
M -->|fork + exec| WN[worker N]
M -->|fork| CM[cache manager]
M -->|fork| CL[cache loader]
M -->|signals: SIGHUP/USR1/USR2/WINCH| M
M -->|socketpair / channel| W1
M -->|socketpair / channel| W2
M -->|socketpair / channel| WN
W1 -->|accept| Clients
W2 -->|accept| Clients
WN -->|accept| ClientsThe master never serves traffic. Its job is to bind listening sockets, parse configuration, fork workers, watch for signals (SIGHUP to reconfigure, SIGUSR1 to reopen logs, SIGUSR2 for binary upgrade), and respawn dead workers. Workers inherit the listening sockets via fork() and run independent event loops.
The implementation lives in src/os/unix/ngx_process_cycle.c (and the Windows port in src/os/win32/ngx_process_cycle.c). See systems/process-model for the full state machine, signal flags (ngx_quit, ngx_terminate, ngx_reconfigure, ngx_reopen, ngx_change_binary), and the binary-upgrade dance that lets a running nginx replace its own executable without dropping connections.
Module model
Everything that nginx does — read a config directive, accept a connection, parse an HTTP request, call OpenSSL, gzip a response, talk to a FastCGI backend — is implemented as a module. A module is a static ngx_module_t struct (src/core/ngx_module.h) with hooks for init_module, init_process, exit_process, plus a commands table that maps directive names to setter functions, plus a typed ctx pointer that adds module-type-specific hooks (ngx_http_module_t, ngx_event_module_t, ngx_mail_module_t, ngx_stream_module_t).
Module types:
| Type | Examples | Where the type's ctx lives |
|---|---|---|
NGX_CORE_MODULE |
ngx_core_module, ngx_http_module, ngx_events_module |
src/core/ngx_module.h |
NGX_EVENT_MODULE |
ngx_epoll_module, ngx_kqueue_module, ngx_poll_module |
src/event/ngx_event.h |
NGX_HTTP_MODULE |
ngx_http_core_module, ngx_http_proxy_module, ngx_http_ssl_* |
src/http/ngx_http_config.h |
NGX_MAIL_MODULE |
ngx_mail_smtp_module, ngx_mail_proxy_module |
src/mail/ngx_mail.h |
NGX_STREAM_MODULE |
ngx_stream_proxy_module, ngx_stream_ssl_module |
src/stream/ngx_stream.h |
NGX_CONF_MODULE |
ngx_conf_module (the include directive) |
src/core/ngx_conf_file.h |
The list of modules baked into a given binary is generated by auto/modules at configure time and emitted as objs/ngx_modules.c. Dynamic modules (loaded via load_module at runtime) use the same struct but ship as .so files. See systems/configuration for how modules register directives and how ngx_init_cycle() walks them on startup and reload.
Event loop
Each worker runs a single thread that loops on ngx_process_events_and_timers() (src/event/ngx_event.c). The actual I/O readiness mechanism is pluggable — there is one event module per OS facility:
| Module | OS | File |
|---|---|---|
ngx_epoll_module |
Linux | src/event/modules/ngx_epoll_module.c |
ngx_kqueue_module |
FreeBSD, macOS | src/event/modules/ngx_kqueue_module.c |
ngx_eventport_module |
Solaris | src/event/modules/ngx_eventport_module.c |
ngx_devpoll_module |
Solaris (legacy) | src/event/modules/ngx_devpoll_module.c |
ngx_poll_module / ngx_select_* |
portable fallback | src/event/modules/ngx_poll_module.c etc. |
ngx_iocp_module |
Windows | src/event/modules/ngx_iocp_module.c |
Each connection (ngx_connection_t, src/core/ngx_connection.h) carries a read event, a write event, and a memory pool whose lifetime matches the connection. Timers ride on a per-worker red-black tree (src/event/ngx_event_timer.c); posted-event lists let modules defer work without re-entering the event loop. See systems/event-loop for the full picture.
HTTP request lifecycle
graph LR
A[accept] --> P[ngx_http_init_connection]
P --> H[read + parse request line + headers]
H --> R[ngx_http_process_request]
R --> Ph[11 phases:<br/>POST_READ → SERVER_REWRITE →<br/>FIND_CONFIG → REWRITE → POST_REWRITE →<br/>PREACCESS → ACCESS → POST_ACCESS →<br/>PRECONTENT → CONTENT → LOG]
Ph --> Hndl[content handler<br/>static / proxy / fastcgi / ...]
Hndl --> F[output filter chain<br/>ssi → range → gzip → chunked → header → write]
F --> N[ngx_http_finalize_request]The 11-phase request engine lives in src/http/ngx_http_core_module.c and src/http/ngx_http_request.c. Modules attach handlers to phases at config-time. Subrequests, internal redirects, try_files, and error_page all unwind through the same phase machinery. See systems/http/request-lifecycle.
Memory model
NGINX almost never calls malloc() in the hot path. Instead:
- Pools (
ngx_pool_t,src/core/ngx_palloc.c) — bump-allocator with cleanup callbacks. One per cycle, one per connection, one per HTTP request, one per subrequest. Freed all at once when the owner ends. - Slab allocators (
ngx_slab_pool_t,src/core/ngx_slab.c) — fixed-size class allocator over a shared-memory zone. Used for SSL session caches, limit-req zones, upstream zones. - Shared memory zones (
ngx_shm_zone_t,src/core/ngx_cycle.h) —mmap'd segments shared between workers. Created viangx_shared_memory_add()during config parsing and re-attached on each reload. - Buffers and chains (
ngx_buf_t+ngx_chain_t,src/core/ngx_buf.h) — every byte that flows through the output filter chain travels in a buffer link. Buffers can be in-memory, file-backed, or both.
See primitives/pool, primitives/buffer, and systems/core for details.
Build pipeline
graph LR
A[auto/configure] -->|probe OS, libs| B[objs/ngx_auto_config.h]
A -->|stitch modules| C[objs/ngx_modules.c]
A -->|emit| D[objs/Makefile]
D -->|gcc / clang| E[objs/*.o]
E -->|link| F[objs/nginx]The auto/ directory is hand-written shell, not autotools. auto/configure invokes auto/options, auto/cc, auto/lib, auto/os, and auto/modules to probe the system, decide which optional features are available, and generate the makefile. There is no ./configure --help autotools convention — flags are documented at nginx.org/en/docs/configure.html. See systems/configuration for the build system and how-to-contribute/tooling for everyday usage.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.