1.进程的描述
1.1进程描述符
为了管理进程,内核必须对每个进程进行清晰的描述,进程描述符提供了内核所需了解的进程信息。
1.2Linux进程状态转换
1.3进程链表
为了对给定类型的进程(比如所有在可运行状态下的进程)进行有效的搜索,内核维护了几个进程链表。
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时,开始执行;
复制内核堆栈时,只是一部分。