CoW is just a lazy optimization. You may freely think that fork()
always makes the full copy of the process (in terms of memory at least) without any delay. But…
If you did prepare dynamic data chunk to "pass" to fork's child, then after fork you have two processes with two dynamic data chunks: parent and child (both are copies). When child exits, it's copy of memory is reclaimed, but parent should free that chunk right after fork by itself.
To be more clear, here is an example:
char *buf = malloc(123456);
// … fill buf for child …
int res = fork();
if (res == -1) {
fprintf(stderr, "fork failed\n");
exit(EXIT_FAILURE);
}
if (res == 0) {
// this is child process
// … do work with buf …
_Exit(EXIT_SUCCESS); // child reclaims buf by means of exit
}
// this is parent process
free(buf); // we don't need it in parent
// … other parent tasks here …
CoW is also very useful optimization in fork-exec technique, where child does nothing but exec
with prepared arguments. exec
replaces current process with specified executable image, retaining open descriptors and other things (more in man 2 execve
). The only page that is copied after such fork is only current stack frame, making fork-exec very effective.
Some systems also provide vfork
, that is very restrictive unfair version of fork, but on systems without CoW that is the only way to vfork-exec efficiently.