zoukankan      html  css  js  c++  java
  • Linux内核分析实验六

    Linux内核分析实验六

    进程控制块PCB——task_struct(进程描述符)

     

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

    struct task_struct数据结构很庞大

    • Linux进程的状态与操作系统原理中的描述的进程状态似乎有所不同,比如就绪状态和运行状态都是TASK_RUNNING,为什么呢?

        TASK_RUNN有没有在CPU上执行决定他是就绪还是运行状态。

            和操作系统类似:就绪态,运行态,阻塞态

    进程的标示pid

        SMP条件编译器

    链表代码——双向链表

    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. /* error occurred */
    11. fprintf(stderr,"Fork Failed!");
    12. exit(-1);
    13. else if (pid == 0)          //可以和后面的else一起执行      两个进程支持输出,并不是打破if---else的规则
    14. {
    15. /* child process */
    16. printf("This is Child Process! ");
    17. else 
    18. /* parent process
    19.  */
    20. printf("This is Parent Process! ");
    21. /* parent will wait for the child to complete*/
    22. wait(NULL);
    23. printf("Child Complete! ");
    24. }
    25. }

     

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

    • 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();函数返回了两次,即在父子进程中各返回一次,父进程从系统调用中返回比较容易理解,子进程从系统调用中返回,那它在系统调用处理过程中的哪里开始执行的呢?

        1. *childregs = *current_pt_regs(); //复制内核堆栈
        2. childregs->ax = 0; //为什么子进程的fork返回0,这里就是原因!
        3. p->thread.sp = (unsigned long) childregs; //调度到子进程时的内核栈顶
        4. p->thread.ip = (unsigned long) ret_from_fork; //调度到子进程时的第一条指令地
      • 这就涉及子进程的内核堆栈数据状态和task_struct中thread记录的sp和ip的一致性问题,这是在哪里设定的?————copy_thread in copy_process

    总结————————————————————创建一个进程的过程:1.复制一份进程描述符(相当于手写一份)——————————————————————————————————————

                                    2.哪些东西不一样:pid,内核堆栈,前一个进程执行位置,记录ip、sp的

                                    3.有修改的,有新的内核堆栈

                                        ——————————构建框架(sys_fork、sys_clone、sys_vfork)

    回顾系统调用

    父进程的调用与系统调用相似

    子进程基本copy子进程——但作为独立进程会被独立调用,独立运行时内核空间在那里执行就成为了问题——对照之前的精简内核

    thread——分配内核堆栈空间

     

    子进程是在哪里开始执行的?

    thread.ip—>ret_from_fork

    pg_regs—>int 0x80做的事情+save_all

    复制这些:

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    Linux 中 java 访问 windows共享目录
    Java中Calender引用类型
    Hadoop MultipleOutputs 结果输出到多个文件夹 出现数据不全,部分文件为空
    转个扯淡的~
    nginx+uwsgi部署python web(web.py)
    关于已经安装python为何还要安装python-dev
    centos7安装mysql5.6
    centos7.0防火墙更换为firewalld
    并发模型(二)——Master-Worker模式
    并发模型(一)——Future模式
  • 原文地址:https://www.cnblogs.com/20135207oneking/p/5338468.html
Copyright © 2011-2022 走看看