进程描述与创建

摘要: mqy + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

 

操作系统的三大功能:进程管理,内层管理,文件系统

最核心:进程管理

进程控制块PCB——task_struct

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

 

进程的pid标示某一进程

 

进程的父子关系管理

 

做调试用:

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();//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. }

fork系统调用在父进程和子进程各返回一次

 

创建一个新进程在内核中的执行过程

  • fork、vfork和clone三个系统调用都可以创建一个新进程,而且都是通过调用do_fork来实现进程的创建;
  • Linux通过复制父进程来创建一个新进程,那么这就给我们理解这一个过程提供一个想象的框架:
  • 复制一个PCB——task_struct
    1. err = arch_dup_task_struct(tsk, orig);
  • 要给新进程分配一个新的内核堆栈
    1. ti = alloc_thread_info_node(tsk, node);
    2. tsk->stack = ti;
    3. setup_thread_stack(tsk, orig); //这里只是复制thread_info,而非复制内核堆栈

 

    • 要修改复制过来的进程数据,比如pid、进程链表等等都要改改吧,见copy_process内部。
  • 从用户态的代码看fork();函数返回了两次,即在父子进程中各返回一次,父进程从系统调用中返回比较容易理解,子进程从系统调用中返回,那它在系统调用处理过程中的哪里开始执行的呢?这就涉及子进程的内核堆栈数据状态和task_struct中thread记录的sp和ip的一致性问题,这是在哪里设定的?copy_thread in copy_process
    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; //调度到子进程时的第一条指令地址

进程穿件概览及fork一个进程的用户态代码

 

理解进程创建过程复杂代码的方法

 

创建新进程是通过复制当前进程来实现的

 

系统调用内核处理函数sys_fork,sys_clone,sys-vfork

 

拷贝内核堆栈数据和指定进程的第一条指令进程

 

Int指令和SAVE_ALL压到内核栈的内容

 

实验:分析linux内核创建一个新进程的过程

过程同上次类似,首先更新MenuOS

gdb调试fork

设置断点并调试

 

linux如何创建一个新进程:Linux通过复制父进程来创建一个新进程,通过调用do_ fork来实现并为每个新创建的进程动态地分配一个task_ struct结构

 

posted @ 2016-04-03 11:13  pottermqy  阅读(167)  评论(0编辑  收藏  举报