zoukankan      html  css  js  c++  java
  • 实验六:分析Linux内核创建一个新进程的过程

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

      1. 题目自拟,内容围绕对Linux系统如何创建一个新进程进行;

      2. 可以结合实验截图、绘制堆栈状态执行流程图等;

      3. 博客内容中需要仔细分析新进程的执行起点及对应的堆栈状态等。

      4. 总结部分需要阐明自己对“Linux系统创建一个新进程”的理解

    上课提问:

    1.进程由哪些部分构成?

    pid,state,task_struct,

    用户堆栈,内核堆栈,地址空间,代码段,数据段

    2.进程是如何被创建?

    0号进程手工创建

    其他进程调用do_frok

    3.新创建的进程从哪里开始执行?

    ret_from_fork

     实验报告:

    1. 阅读理解task_struct数据结构http://codelab.shiyanlou.com/xref/linux-3.18.6/include/linux/sched.h#1235

      1. state:运行状态
      2. stack:内核堆栈
      3. tasks:进程链表
      4. mm:内存管理
      5. task_state:任务的状态
      6. pid:进程PID
      7. real_parent children:进程的父子关系
      8. files:文件描述符列表
      9. signal:信号处理相关
      10. splice_pipe:管道相关
    2. 分析fork函数对应的内核处理过程sys_clone,理解创建一个新进程如何创建和修改task_struct数据结构;

      1. fork、vfork和clone三个系统调用都可以创建一个新进程,都是通过调用do_fork来实现进程的创建
      2. 创建新进程需要先复制一个PCB:task_struct
      3. 再给新进程分配一个新的内核堆栈 
        ti = alloc_thread_info_node(tsk, node);
        tsk->stack = ti;
        setup_thread_stack(tsk, orig); //这里只是复制thread_info,而非复制内核堆栈
      4. 再修改复制过来的进程数据,比如pid、进程链表等等,见copy_process内部
      5. 从用户态的代码看fork();函数返回了两次,即在父子进程中各返回一次
        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; //调度到子进程时的第一条指令地址
      6. do_fork完成了创建中的大部分工作,该函数调用copy_process()函数,然后让进程开始运行。copy_process()函数工作如下:

        • 1、调用dup_task_struct()为新进程创建一个内核栈、thread_info结构和task_struct,这些值与当前进程的值相同
        • 2、检查
        • 3、子进程着手使自己与父进程区别开来。进程描述符内的许多成员被清0或设为初始值。
        • 4、子进程状态被设为TASK_UNINTERRUPTIBLE,以保证它不会投入运行
        • 5、copy_process()调用copy_flags()以更新task_struct的flags成员。表明进程是否拥有超级用户权限的PF_SUPERPRIV标志被清0。表明进程还没有调用exec()函数的PF_FORKNOEXEC标志被设置
        • 6、调用alloc_pid()为新进程分配一个有效的PID
        • 7、根据传递给clone()的参数标志,copy_process()拷贝或共享打开的文件、文件系统信息、信号处理函数、进程地址空间和命名空间等
        • 8、最后,copy_process()做扫尾工作并返回一个指向子进程的指针
    3. 使用gdb跟踪分析一个fork系统调用内核处理函数sys_clone ,验证您对Linux系统创建一个新进程的理解

      1. 下断点的函数:sys_clone do_fork dup_task_struct  copy_process copy_thread ret_from_fork
      2. dup_task_struct()为新进程创建一个内核栈
      3. copy_process()主要完成进程数据结构,各种资源的初始化
    4. 特别关注新进程是从哪里开始执行的?为什么从哪里能顺利执行下去?即执行起点与内核堆栈如何保证一致。

      1. ret_from_fork;决定了新进程的第一条指令地址
      2. copy_thread()函数中的语句p->thread.ip = (unsigned long) ret_from_fork;决定了新进程的第一条指令地址
      3. 在ret_from_fork之前,也就是在copy_thread()函数中*childregs = *current_pt_regs();该句将父进程的regs参数赋值到子进程的内核堆栈
      4. *childregs的类型为pt_regs,里面存放了SAVE ALL中压入栈的参数 故在之后的RESTORE ALL中能顺利执行下去
    ========================if i have some wrong, please give me a message, thx.========================
  • 相关阅读:
    刷题-力扣-152. 乘积最大子数组
    刷题-力扣-剑指 Offer II 088. 爬楼梯的最少成本
    刷题-力扣-剑指 Offer II 003. 前 n 个数字二进制中 1 的个数
    刷题-力扣-LCS 01. 下载插件
    刷题-力扣-剑指 Offer 10- II. 青蛙跳台阶问题
    20191107-3 beta week 2/2 Scrum立会报告+燃尽图 02
    beta week 2/2 Scrum立会报告+燃尽图 01
    版本控制报告
    20191031-9 beta week 1/2 Scrum立会报告+燃尽图 07
    扛把子组20191031-2 Beta阶段贡献分配规则
  • 原文地址:https://www.cnblogs.com/ailx10/p/5341432.html
Copyright © 2011-2022 走看看