用于创建进程的 fork 和 execve 函数

Linux 中创建进程有两个目的:

  • 将一个程序分为多个进程进行处理
  • 创建另一个新的进程

为了达到上面两个目的,Linux 提供了 fork 和 execve 函数来创建进程。

fork 函数

fork 函数能够将一个程序分成多个进程进行处理,调用 fork() 后,就会创建一个新的进程,发出请求的是父进程,创建的新进程是子进程。

fork() 创建新进程的流程:

  • 为子进程申请内存,并复制父进程内存数据到子进程内存空间。
  • 分裂成父进程和子进程,分别执行不同的代码。
  • 在父进程时,fork() 返回子进程 pid;在子进程时,返回 0;fork 失败返回 - 1。

微信图片_20230104165513

测试用例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h> // provide a declaration of exit()
#include <err.h>

int main() {
pid_t pid = fork();
if (pid == -1)
err(EXIT_FAILURE, "fork() failed");
if (pid == 0) {
// child process came here because fork() returns 0 for child process
printf("I'm child! my pid is %d.\n", getpid());
exit(EXIT_SUCCESS);
} else {
// parent process came here because fork() returns the pid of newly created child process (> 1)
printf("I'm parent! my pid is %d and the pid of my child is %d.\n", getpid(), pid);
exit(EXIT_SUCCESS);
}
}

运行结果:

1
2
3
lhx@ubuntu:~/book-demo/how_linux_works/chapter_3$ ./fork
I'm parent! my pid is 4015 and the pid of my child is 4016.
I'm child! my pid is 4016.

execve 函数

启动另一个新的程序时,需要调用 execve() 函数,其启动新程序的流程是:

  • 读取可执行文件中创建进程内存映像所需的数据。
  • 用新进程数据覆盖当前进程的内存。
  • 从头开始运行新的进程。

微信图片_20230104165518

测试用例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h> // provide a declaration of exit()
#include <err.h>

int main() {
pid_t pid = fork();
if (pid == -1)
err(EXIT_FAILURE, "fork() failed");
if (pid == 0) {
// child process came here because fork() returns 0 for child process
char *args[] = { "/bin/echo", "hello world!" , NULL};
printf("I'm child! my pid is %d.\n", getpid());
fflush(stdout);
execve("/bin/echo", args, NULL);
err(EXIT_FAILURE, "exec() failed");
} else {
// parent process came here because fork() returns the pid of newly created child process (> 1)
printf("I'm parent! my pid is %d and the pid of my child is %d.\n", getpid(), pid);
exit(EXIT_SUCCESS);
}
}

运行结果:

1
2
3
4
lhx@ubuntu:~/book-demo/how_linux_works/chapter_3$ ./fork-and-exec 
I'm child! my pid is 4027.
I'm parent! my pid is 4026 and the pid of my child is 4027.
hello world!