c++ fork 程序時 共享記憶體_Windows下的PostgreSQL程序fork
Windows系統API我並不熟悉,所以本篇大致點出過程,更多細節還請閱讀程式碼和詳查微軟文件。後邊還會有一篇講Windows下訊號處理的模擬,內容跟這篇是關聯的。
這篇文章假定讀者已經瞭解*nix的fork,如果不瞭解,請自行閱讀相關資料。
1、*nix下PG後端(backend)程序的發起:
static intBackendStartup(Port *port){...#ifdef EXEC_BACKEND pid = backend_forkexec(port);#else /* !EXEC_BACKEND */ pid = fork_process(); if (pid == 0) /* child */{...
當然這裡還有一些其他邏輯,不細表,有興趣可以自己瞅瞅,都不復雜。
2、函式 fork_process
程式碼位於 src/backend/postmaster/fork_process.c
, 沒有什麼很複雜的邏輯:
#ifndef WIN32...pid_tfork_process(void){...result = fork();if (result == 0){
注意:這裡有preprocessor,上邊這段程式碼是 #ifndef WIN32
控制,也就是隻在 *nix下有效。
3、Windows下的後端程序建立
編譯Windows版的方法,可以自行閱讀,它不一樣的地方之一是啟用預處理符 EXEC_BACKEND
函式 backend_forkexec
中:
av[ac++] = "postgres";av[ac++] = "--forkbackend";
這裡增加兩個引數,一個是程式啟動的檔名,一個是引數forkbackend,指定這是要啟動一個fork後端的程序,啟動過程中會有一些影響:
if (strcmp(argv[1], "--forkbackend") == 0 ||... PGSharedMemoryReAttach();
4、引數傳遞
fork()不需要考慮變數傳遞的問題,EXEC_BACKEND
時儲存到臨時檔案裡:
paramHandle = CreateFileMapping(INVALID_HANDLE_VALUE,...param = MapViewOfFile(paramHandle, ......if (!save_backend_variables(param, port, pi.hProcess, pi.dwProcessId))...
這部分程式碼在 EXEC_BACKEND
函式實現 internal_forkexec
裡,可以結合Windows文件去理解。
5、為新程序準備共享記憶體
if (!pgwin32_ReserveSharedMemoryRegion(pi.hProcess))
以後有機會寫共享記憶體時再寫,感覺尤其是Windows下挺有必要。
6、程序建立
在呼叫 save_backend_variables
之前:
if (!CreateProcess(NULL, cmdLine, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)){
這裡 cmdLine
是 安裝路徑\postgres.exe --forkbackend nnn
,最後一個引數是引數處理控制代碼,第一個引數的計算前幾天寫過。
從微軟文件看,並沒有說新建立的程序與postmaster之間是父子關係:
Creates a new process and its primary thread. The new process runs in the security context of the calling process.
7、後端程序啟動不一樣的處理分支
Windows下呼叫 SubPostmasterMain
:
...#ifdef EXEC_BACKEND if (argc > 1 && strncmp(argv[1], "--fork", 6) == 0) SubPostmasterMain(argc, argv); /* does not return */#endif...
此函式位於:src/backend/postmaster/postmaster.c
SubPostmasterMain(int argc, char *argv[])
8、引數讀入
在Windows下,讀取由 CreateFileMapping
建立的檔案對映控制代碼:
#ifdef _WIN64 paramHandle = (HANDLE) _atoi64(id);#else paramHandle = (HANDLE) atol(id);#endif paramp = MapViewOfFile(paramHandle, FILE_MAP_READ, 0, 0, 0);
9、共享記憶體ReAttach
if (strcmp(argv[1], "--forkbackend") == 0 || strcmp(argv[1], "--forkavlauncher") == 0 || strcmp(argv[1], "--forkavworker") == 0 || strcmp(argv[1], "--forkboot") == 0 || strncmp(argv[1], "--forkbgworker=", 15) == 0) PGSharedMemoryReAttach();
大致就是這些。
如果覺得公眾號閱讀程式碼不便,可以訪問我的部落格:https://my.oschina.net/quanzl/,或者使用電腦版微信。
歡迎關注
歡迎關注飛象資料