20135327郭皓--Linux内核分析第六周 进程的描述和进程的建立

进程的描述和进程的建立

1、进程的描述

操做系统三大功能:数据结构

  • 进程管理
  • 内存管理
  • 文件系统

进程描述符task_struct数据结构atom

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

  • 进程的状态:Linux进程的状态(就绪态、运行态、阻塞态)操作系统

  • 进程的标示pid:用来标示进程线程

进程状态转化

进程描述符task_struct数据结构(重要部分):3d

 1 struct task_struct {
 2 volatile long state;    /* 进程的运行状态-1 unrunnable, 0 runnable, >0 stopped */
 3 void *stack;    /*指定了进程的内核堆栈*/
 4 atomic_t usage;
 5 unsigned int flags; /* 每个进程的标识符 */
 6 
 7 int on_rq;  /*运行队列*/
 8 
 9 pid_t pid; /*进程标识符*/
10 
11 struck list_head task;  /*进程链表*/
12 
13 /*父子进程*/
14 struct task_struct __rcu *real_parent; /* real parent process */
15 struct task_struct __rcu *parent; 
16 
17 struct list_head children;    /* list of my children */

 

2、进程的建立

start _ kernel代码中的rest _ init建立两个内核线程,kernel _ init和kthreadd。调试

kernel _ init将用户态进程init启动,是全部用户态进程的祖先。rest

kthreadd是全部内核线程的祖先。code

0号进程是全部线程的祖先。(0号进程时手工写的)orm

fork一个子进程的代码:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 int main(int argc, char * argv[])
 5 {
 6     int pid;
 7     /* fork another process */
 8     pid = fork();
 9     if (pid < 0) 
10     { 
11         /* error occurred */
12         fprintf(stderr,"Fork Failed!");
13         exit(-1);
14     } 
15     else if (pid == 0) 
16     {
17         /* child process */
18         printf("This is Child Process!\n");
19     } 
20     else 
21     { 
22         /* parent process  */
23         printf("This is Parent Process!\n");
24         /* parent will wait for the child to complete*/
25         wait(NULL);
26         printf("Child Complete!\n");
27     }
28 }

这里特别说明一下:else if和if两个模块的代码都会被执行,子进程和父进程都会返回,子进程返回0,父进程返回子进程pid。

 

 

实验:

1. 删除menu,克隆新的menu。

 

2.查看help

3.gdb调试

4.设置断点

5.单步追踪

 

总结:

新的进程从哪里开始?

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

Linux经过复制父进程来建立一个新进程:复制父进程PCB--task_struct来建立一个新进程,要给新进程分配一个新的内核堆栈。

修改复制过来的进程数据,好比pid、进程链表等等执行copy_process和copy_thread。

设置sp调度到子进程时的内核栈顶,ip转到子进程时的第一条指令地址

以后,当子进程得到CPU的控制权开始运行的时候,ret _ form _ fork能够将后面的堆栈出栈,从iret返回到用户态,从而切换到子进程的用户空间,完成新进程的建立。

相关文章
相关标签/搜索