浅学进程的创建

42 阅读2分钟

创建进程的大体过程

image.png

进程创建:系统调用sys_fork

目的:创建一个新的进程

本质:在内核中创建一个 ”task_struct“ 实例或对象,然后将task_struct维护到各种链表(用于管理和调度进程)中

注意:不是创建全新的task_struct,而是拷贝(copy)父进程的task_struct

创建进程的详细过程

image.png

fork() 返回的 pid 与 实际进程 PID 的区别

  1. fork() 的返回值

pid_t pid = fork();

  • pid = 0: 在子进程的代码空间中,表示当前是子进程
  • pid > 0: 在父进程的代码空间中,返回的是子进程的实际 PID
  • pid = -1: fork 失败
  1. 实际进程 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

关键理解点

  1. fork() 返回值是"视角相关"的:

    • 在子进程中返回 0("你是子进程")
    • 在父进程中返回子进程的实际 PID
  2. 子进程确实有自己的 PID:

    • 子进程可以通过 getpid() 获得自己的真实 PID
    • 父进程可以通过 fork() 的返回值获得子进程的 PID
  3. 设计目的:

    • 让两个进程轻松区分自己的角色
    • 让父进程能够跟踪和管理子进程

简单来说:fork() 返回值是角色标识符,不是真实的进程PID。子进程有自己真实的 PID,只是通过 fork() 返回 0 来标识自己的角色。

image.png

exec组函数

image.png