Deep Dive into PHP‑FPM Startup, Process Management, Event Loop, and Shared Memory

This article explains the internal architecture of PHP‑FPM, covering its startup sequence, master‑worker process management, event‑driven loop, signal handling, shared‑memory scoreboard implementation, and the overall request lifecycle, with detailed code excerpts and diagrams.

Beike Product & Technology
Beike Product & Technology
Beike Product & Technology
Deep Dive into PHP‑FPM Startup, Process Management, Event Loop, and Shared Memory

PHP‑FPM is a FastCGI process manager that creates a master process and multiple worker processes to handle PHP requests. The master process starts by initializing the SAPI layer, reading configuration, and then launching workers according to the chosen process manager (dynamic or on‑demand).

1. Startup Process

From a code‑execution perspective, PHP is a script interpreter. The top‑most layer is the SAPI (Server Application Programming Interface) which connects PHP to the web server. The most common modes are cli and fpm, and the article focuses on the FPM mode.

Key steps of the FPM master startup include:

Execute sapi_startup to set the global sapi_module to cgi_sapi_module.

Call cgi_sapi_module.startup, which invokes php_module_startup.

Initialize FPM configuration via fpm_init, parsing the configuration file, creating worker pools, initializing scoreboards, and setting up signal handling.

Finally, call fpm_run to fork worker processes and enter the event loop.

2. Process Management

The master creates a struct fpm_worker_pool_s for each pool, which contains configuration, socket descriptors, and runtime data such as the list of child workers. Workers are forked from the master; the master monitors them via shared memory and can send signals to terminate or reload them.

When the process manager is set to ondemand, the master registers a socket event that creates a worker only when a request arrives.

int fpm_children_create_initial(struct fpm_worker_pool_s *wp) {
    if (wp->config->pm == PM_STYLE_ONDEMAND) {
        wp->ondemand_event = malloc(sizeof(struct fpm_event_s));
        /* set callback to fpm_pctl_on_socket_accept */
        fpm_event_set(wp->ondemand_event, wp->listening_socket,
            FPM_EV_READ | FPM_EV_EDGE, fpm_pctl_on_socket_accept, wp);
        fpm_event_add(wp->ondemand_event, 0);
        return 1;
    }
    return fpm_children_make(wp, 0, 0, 1);
}

The master also runs periodic maintenance (heartbeat) timers to check for request timeouts and to dynamically adjust the number of workers.

3. Event Mechanism

FPM implements a simple event system that abstracts both timer and file‑descriptor events. Two queues are maintained: one for timer events and one for FD events. The event module (epoll, kqueue, etc.) provides init, wait, add, and remove callbacks.

struct fpm_event_module_s {
    const char *name;
    int support_edge_trigger;
    int (*init)(int max_fd);
    int (*clean)(void);
    int (*wait)(struct fpm_event_queue_s *queue, unsigned long int timeout);
    int (*add)(struct fpm_event_s *ev);
    int (*remove)(struct fpm_event_s *ev);
};

The main loop ( fpm_event_loop) adds the signal‑fd event, heartbeat timer, and worker‑maintenance timer, then repeatedly calls the module’s wait function. When wait returns, timer callbacks are fired, and any ready FD events are dispatched via fpm_event_fire.

4. Shared Memory

Both master and workers need to access the scoreboard that records each worker’s state. This is implemented using an anonymous shared memory segment created with mmap:

void *fpm_shm_alloc(size_t size) {
    void *mem = mmap(0, size, PROT_READ | PROT_WRITE,
        MAP_ANONYMOUS | MAP_SHARED, -1, 0);
    if (mem == MAP_FAILED) {
        /* handle error */
        return NULL;
    }
    return mem;
}

The scoreboard consists of struct fpm_scoreboard_s (global pool info) and an array of struct fpm_scoreboard_proc_s (per‑worker stats). Because the memory is shared, after fork the child workers inherit the same pointer and can update their own entries.

5. Lifecycle

From a request perspective, each worker follows the sequence: module_startup (once at process start), request_startup, execute_script, request_shutdown, and finally module_shutdown when the process exits. The article notes that the first three steps are performed for every request, while the startup/shutdown steps occur only when the FPM service starts or stops.

Overall, the article provides a comprehensive walkthrough of PHP‑FPM’s internal workflow, from initialization through event‑driven request handling, worker management, signal processing, and shared‑memory coordination.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Backendprocess managementshared memoryevent loopphp-fpm
Beike Product & Technology
Written by

Beike Product & Technology

As Beike's official product and technology account, we are committed to building a platform for sharing Beike's product and technology insights, targeting internet/O2O developers and product professionals. We share high-quality original articles, tech salon events, and recruitment information weekly. Welcome to follow us.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.