进程的描述和进程的创建

1.进程的描述

1.1进程描述符

为了管理进程,内核必须对每个进程进行清晰的描述,进程描述符提供了内核所需了解的进程信息。

1.2Linux进程状态转换

image

1.3进程链表

为了对给定类型的进程(比如所有在可运行状态下的进程)进行有效的搜索,内核维护了几个进程链表。

image

2进程的创建

2.1进程的创建概览及一个简单的用户态代码

2.1.1概览

道生一(start_kernel…cpu_idle),一生二(kernel_init、kthread),二生三(即0、1、2三个进程),三生万物(1号进程是所有用户态进程的祖先,2号进程是所有内核线程的祖先)。

PS:子进程可以通过规范的创建进程的函数(如:fork())基于父进程复制创建,那么0号进程就是没有可以复制和参考的对象,也就是说0号进程拥有的所有信息和资源都是强制设置的,不是复制的,这个过程我称为手工设置,这是操作系统中“最原始”的一个进程,它是一个模子,后面的任何进程都是基于0号进程生成的。

2.1.2fork一个子进程的代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char * argv[])
{
    int pid;
    /* fork another process */
    pid = fork();
    if (pid < 0) 
    { 
        /* error occurred */
        fprintf(stderr,"Fork Failed!");
        exit(-1);
    } 
    else if (pid == 0) 
    {
        /* child process */
        printf("This is Child Process!
");
    } 
    else 
    {  
        /* parent process  */
        printf("This is Parent Process!
");
        /* parent will wait for the child to complete*/
        wait(NULL);
        printf("Child Complete!
");
    }
}

2.2Linux通过复制父进程来创建一个新进程的一个框架

  • 复制一个PCB——task_struct
  • 给新进程分配一个新的内核堆栈
  • 修改复制过来的进程数据,比如pid、进程链表等等

2.3创建的新进程执行的起点

*childregs = *current_pt_regs(); //复制内核堆栈
childregs->ax = 0; //为什么子进程的fork返回0,这里就是原因!
 
p->thread.sp = (unsigned long) childregs; //调度到子进程时的内核栈顶
p->thread.ip = (unsigned long) ret_from_fork; //调度到子进程时的第一条指令地址

ret_from_fork,子进程得到进程调度,CPU时,开始执行;

复制内核堆栈时,只是一部分。

原文地址:https://www.cnblogs.com/boyiliushui/p/5478135.html