1. 程式人生 > 其它 >c++ fork 程序時 共享記憶體_Windows下的PostgreSQL程序fork

c++ fork 程序時 共享記憶體_Windows下的PostgreSQL程序fork

技術標籤:c++ fork 程序時 共享記憶體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

。這個開關在*nix一樣有效,有興趣可以自己試試啟用它編譯Linux版,個人感覺程序fork效率一定要低很多。

函式 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/,或者使用電腦版微信。

歡迎關注

dfa0aa172ab83b83c3f19601434a371a.png

歡迎關注飛象資料

7e2ee4e1d5980ef2a239bbd5d46ea8d5.png