這個問題在這里已經有了答案: 釋放未更改的“寫時復制”記憶體 2 個答案 昨天關門。
來自man fork(2):
Under Linux, fork() is implemented using copy-on-write pages, so
the only penalty that it incurs is the time and memory required
to duplicate the parent's page tables, and to create a unique
task structure for the child.
因此,在這樣的示例中:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
char *data = malloc(100);
snprintf(data, 100, "%s", "Hello world!");
pid_t pid = fork();
if (pid == -1)
{
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0)
{
// start of child process
printf("I'm the child\n");
// Do the child stuff ...
puts(data);
}
else
{
// start of parent process
printf("I'm the parent\n");
// Do the parent stuff ...
puts(data);
// Wait for child process
if (wait(NULL) == -1)
{
perror("wait");
exit(EXIT_FAILURE);
}
free(data);
}
return 0;
}
據我了解,如果資源被復制但未修改,則無需創建新資源,并且保留的記憶體malloc不會在分叉行程中復制/復制,而是我們得到一個指向在父行程中保留的記憶體的指標程序。
另一方面,如果資源沒有在子行程中釋放,我們就會得到記憶體泄漏:
==13024== HEAP SUMMARY:
==13024== in use at exit: 100 bytes in 1 blocks
==13024== total heap usage: 2 allocs, 1 frees, 1,124 bytes allocated
==13024==
==13024== LEAK SUMMARY:
==13024== definitely lost: 100 bytes in 1 blocks
==13024== indirectly lost: 0 bytes in 0 blocks
==13024== possibly lost: 0 bytes in 0 blocks
==13024== still reachable: 0 bytes in 0 blocks
==13024== suppressed: 0 bytes in 0 blocks
==13024== Rerun with --leak-check=full to see details of leaked memory
==13024==
==13024== For lists of detected and suppressed errors, rerun with: -s
==13024== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==13023==
==13023== HEAP SUMMARY:
==13023== in use at exit: 0 bytes in 0 blocks
==13023== total heap usage: 2 allocs, 2 frees, 1,124 bytes allocated
==13023==
==13023== All heap blocks were freed -- no leaks are possible
==13023==
==13023== For lists of detected and suppressed errors, rerun with: -s
==13023== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
這表明您應該free()從分叉的行程中呼叫。
if (pid == 0)
{
// start of child process
printf("I'm the child\n");
// Do the child stuff ...
puts(data);
free(data);
}
分叉行程中的呼叫是否會free()導致寫時復制?
uj5u.com熱心網友回復:
是的,確實如此。
記憶體寫入時復制 (CoW) 發生在與malloc()/不同的層上free()。
當一個行程被派生時,子行程將其所有映射頁面標記為與父行程共享(因此是只讀的)。當子行程修改共享頁面時,它會觸發頁面錯誤,然后作業系統才會將資料復制到物理 RAM 中的另一個區域(并更改行程的映射)。
malloc()并且free()不分配物理 RAM。它們是記憶體管理功能,記憶體定義為“行程的(虛擬)地址空間”。因此,這些 C 庫函式跟蹤分配的記憶體塊的內部狀態,malloc()并且free()只修改這些 libc 內部資料結構(除了在malloc()-ing 時向作業系統請求更多地址空間)。物理 RAM 分配僅發生在頁面錯誤時,最常見于行程第一次訪問新分配的記憶體時。
在這方面,是的。由于free()必須修改記憶體以將區域標記為已釋放,它將寫入相關區域,并在較低級別導致重新映射(即 CoW)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/507342.html
下一篇:如何更有效地使用此陳述句
