乐闻世界logo
搜索文章和话题

The difference between fork(), vfork(), exec() and clone()

1个答案

1

In Linux system programming, fork(), vfork(), exec(), and clone() are system calls for process control, but their purposes and behaviors differ.

1. fork()

fork() is used to create a new process, called the child process, which is a copy of the parent process. It copies all memory space, open file descriptors, and other resources from the parent process. Both the parent and child processes resume execution from the instruction immediately following the fork() call.

Example:

c
#include <stdio.h> #include <unistd.h> int main() { pid_t pid = fork(); if (pid == 0) { // Child process code printf("This is child process\n"); } else { // Parent process code printf("This is parent process\n"); } return 0; }

2. vfork()

vfork() is also used to create a child process, but it differs from fork(). The child process created by vfork() shares the parent process's address space (without immediately copying the entire address space). The child process runs first, and the parent process is scheduled to run only after the child calls exec() or exit(). vfork() is primarily used when the child process is expected to call exec() or exit() soon, to avoid unnecessary address space copying.

Example:

c
#include <stdio.h> #include <unistd.h> #include <stdlib.h> int main() { pid_t pid = vfork(); if (pid == 0) { // Child process code printf("This is child process\n"); _exit(0); // Note: _exit() is used instead of exit() } else { // Parent process code printf("This is parent process\n"); } return 0; }

3. exec()

The exec() family of functions is used to execute a new program within the current process. It replaces the current process's address space with that of the new program, but the process ID remains unchanged. exec() is commonly called after fork() or vfork() to run the new program in the child process.

Example:

c
#include <stdio.h> #include <unistd.h> int main() { pid_t pid = fork(); if (pid == 0) { // Child process code execlp("ls", "ls", NULL); } else { // Parent process continues wait(NULL); // Wait for child process to finish } return 0; }

4. clone()

clone() is a more flexible way to create processes compared to fork(). It allows the caller to specify which resources are shared between the parent and child processes, such as file descriptors and address space. By passing different flags, it can achieve behaviors similar to fork(), vfork(), or threads (lightweight processes).

Example:

c
#define _GNU_SOURCE #include <stdio.h> #include <sched.h> #include <unistd.h> #include <sys/wait.h> int child_func(void* arg) { printf("This is child process\n"); return 0; } int main() { const int STACK_SIZE = 65536; // Stack size char* stack = malloc(STACK_SIZE); if (!stack) { perror("Failed to allocate stack"); exit(1); } unsigned long flags = CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_VM; pid_t pid = clone(child_func, stack + STACK_SIZE, flags, NULL); waitpid(pid, NULL, 0); free(stack); return 0; }

These system calls are foundational to the operating system and are crucial. I hope these explanations and examples will help you understand the distinctions between them.

2024年8月22日 16:31 回复

你的答案