首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Nginx 多進程模型簡化版 Demo 實現:Master-Worker 架構與進程標題修改

     編輯:關於C語言

Nginx 進程模型核心

  • Master 進程:讀取配置、綁定端口、管理 Worker 進程生命周期(啟動/重啟/平滑升級)。
  • Worker 進程:實際處理客戶端請求,多進程並發,互不干擾。
  • 可選 Dispatcher/Cache Manager 等輔助進程。

關鍵技術點:進程標題修改 (setproctitle)

Nginx 通過覆蓋 argv 內存區,讓 ps 顯示自定義進程名(如 nginx: worker process),便於運維識別。

實現原理

  1. 啟動時保存 argv 指針數組地址與 argv[0] 末尾地址 os_argv_last。
  2. setproctitle() 將新標題拷貝到 argv[0],剩餘空間填空格,argv[1]=NULL 截斷後續參數顯示。

完整 Demo 代碼

#include 
#include 
#include 

char **os_argv;
char *os_argv_last;

void init_setproctitle(void) {
    os_argv_last = os_argv[0];
    for (int i = 0; os_argv[i]; ++i) {
        if (os_argv_last == os_argv[i])
            os_argv_last = os_argv[i] + strlen(os_argv[i]) + 1;
    }
    os_argv_last += strlen(os_argv_last);  // 指向環境變量區起始
}

void setproctitle(const char *title) {
    os_argv[1] = NULL;
    char *p = strncpy((char *)os_argv[0], title, strlen(title));
    p += strlen(title);
    if (os_argv_last > p)
        memset(p, ' ', os_argv_last - p);
}

void save_argv(int argc, char *const *argv) { os_argv = (char **)argv; }

void worker_process() {
    setproctitle("mynginx: worker process");
    for (;;) {
        sleep(1);
        printf("worker pid=%d\n", getpid());
    }
}

void dispatcher_process() {
    setproctitle("mynginx: dispatcher process");
    for (;;) {
        sleep(1);
        printf("\tdispatcher pid=%d\n", getpid());
    }
}

int main(int argc, char **argv) {
    save_argv(argc, argv);
    init_setproctitle();

    printf("master pid=%d\n", getpid());

    // 啟動 3 個 worker
    for (int i = 0; i < 3; ++i) {
        if (fork() == 0) worker_process();
    }
    // 啟動 1 個 dispatcher
    if (fork() == 0) dispatcher_process();

    // Master 進程主循環
    for (;;) sleep(1);
    return 0;
}

編譯運行與驗證

$ gcc mynginx.c -o mynginx
$ ./mynginx
master pid=20553
worker pid=20554
worker pid=20555
worker pid=20556
	dispatcher pid=20557
$ ps -ef | grep mynginx
test 20553 20463  0 23:54 pts/0  00:00:00 ./mynginx
test 20554 20553  0 23:54 pts/0  00:00:00 mynginx: worker process
test 20555 20553  0 23:54 pts/0  00:00:00 mynginx: worker process
test 20556 20553  0 23:54 pts/0  00:00:00 mynginx: worker process
test 20557 20553  0 23:54 pts/0  00:00:00 mynginx: dispatcher process

關鍵細節解析

點說明
fork 後關閉無用 fd真實 Nginx 中子進程關閉聽套接字,父進程關閉連接套接字;Demo 簡化省略
信號處理Master 需處理 SIGCHLD 回收僵屍進程、SIGHUP 平滑重載;Demo 未演示
共享內存/鎖多 Worker accept 同一端口需 accept_mutex 序列化;Demo 未涉及網絡
argv 內存佈局argv 緊鄰 environ,修改 argv 區不影響環境變量;跨平台需注意對齊

擴展方向

  • 加入 epoll/kqueue 事件循環實現真正的 HTTP 服務。
  • 實現平滑升級:Master 收到 SIGUSR2 啟動新 Master,舊 Worker 逐步退出。
  • 共享內存區存儲統計計數器、緩存元數據。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved