创建进程的大体过程
进程创建:系统调用sys_fork
目的:创建一个新的进程
本质:在内核中创建一个 ”task_struct“ 实例或对象,然后将task_struct维护到各种链表(用于管理和调度进程)中
注意:不是创建全新的task_struct,而是拷贝(copy)父进程的task_struct
创建进程的详细过程
fork() 返回的 pid 与 实际进程 PID 的区别
- fork() 的返回值
pid_t pid = fork();
- pid = 0: 在子进程的代码空间中,表示当前是子进程
- pid > 0: 在父进程的代码空间中,返回的是子进程的实际 PID
- pid = -1: fork 失败
- 实际进程 PID
每个进程都有自己唯一的实际 PID,可以通过 getpid() 获取。
伪代码示例说明
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
pid_t fork_pid = fork();
if (fork_pid == 0) {
// 子进程代码
printf("子进程: fork()返回=%d, 我的实际PID=%d, 父进程PID=%d\n", fork_pid, getpid(), getppid());
// 这里可以执行 execve()
} else if (fork_pid > 0) {
// 父进程代码
// fork() 返回的是子进程的实际PID
printf("父进程: fork()返回=%d, 我的实际PID=%d\n", fork_pid, getpid());
} else {
perror("fork failed");
}
return 0;
}
可能的输出:
父进程: fork()返回=12345, 我的实际PID=12344 子进程: fork()返回=0, 我的实际PID=12345, 父进程PID=12344
关键理解点
-
fork() 返回值是"视角相关"的:
- 在子进程中返回 0("你是子进程")
- 在父进程中返回子进程的实际 PID
-
子进程确实有自己的 PID:
- 子进程可以通过 getpid() 获得自己的真实 PID
- 父进程可以通过 fork() 的返回值获得子进程的 PID
-
设计目的:
- 让两个进程轻松区分自己的角色
- 让父进程能够跟踪和管理子进程
简单来说:fork() 返回值是角色标识符,不是真实的进程PID。子进程有自己真实的 PID,只是通过 fork() 返回 0 来标识自己的角色。