第六章 进程的描述和进程的创建

知识点总结

进程的描述

  • 操作系统内核实现操作系统的三大管理功能以及对应的抽象概念:

    • 进程管理(最核心)—— 进程
    • 内存管理 —— 虚拟内存
    • 文件系统 —— 文件
  • 进程是怎样描述的?
    • 通过进程控制块PCB描述进程
  • Linux内核中用数据结构 struct task_struct 来描述进程,称其为进程描述符
  • 进程描述符的结构示意图:

  • Linux内核管理的进程状态转化图:

  • 注意:操作系统原理中就绪态和运行态这两个状态在Linux内核中都是相同的 TASK_RUNNING 状态。在Linux内核中,当进程是 TASK_RUNNING 状态时,它是可运行的,也就是就绪态,是否运行取决于它有没有获得CPU的控制权。
  • 阻塞态也有两种:TASK_INTERRUPTIBLE 和 TASK_UNINTERRUPTIBLE 。
    • TASK_INTERRUPTIBLE 状态是可以被信号和 wake_up() 唤醒的。
    • TASK_UNINTERRUPTIBLE 状态只能被 wake_up() 唤醒的。
  • 进程标识符PID。在进程描述符中用pid和tgid标识进程。
  • 管理进程数据结构的双向链表:struct list_head tasks (是一个很关键的进程链表)

进程的创建

0号进程的初始化

  • 0号进程 init_task 的初始化时通过硬件编码方式固定下来的。(其他的所有进程都是通过 do_fork 复制父进程的方式初始化的)

内存管理相关代码

1301  struct mm_struct *mm,*active_mm;

mm 和 active_mm 是和进程地址空间,内存管理相关的数据结构指针。

进程之间的父子、兄弟关系

  • 进程描述符 struct task_struct 数据结构中记录了当前进程的父进程 real_parent;记录当前进程的子进程的是双向链表 struct list_head children;记录当前进程的兄弟进程的是双向链表 struct list_head sibling。

保存进程上下文中CPU相关的一些状态信息的数据结构

  • 数据结构 struct thread_struct 用来保存进程上下文中CPU相关的一些状态信息的数据结构,在进程切换时起着很重要的作用。
  • struct thread_struct 数据结构中最关键的是 sp 和 ip:
    • sp 用来保存进程上下文中ESP寄存器状态
    • ip 用来保存进程上下文中EIP寄存器状态

进程的创建过程分析

  • rest_init 通过 kernel_thread 创建两个内核线程:

    • kernel_init (1号进程),是所有用户态进程的祖先。
    • kthreadd 内核线程 (2号进程),是所有内核线程的祖先,负责管理所有内核线程。
  • fork,vfork,clone 三个系统调用都可以创建一个新进程,而且都可通过调用 do_fork 来实现进程的创建。
  • fork 一个子进程的过程中,复制父进程的资源采用了Copy On Write(写时复制)技术。不需要修改进程资源,父子进程是共享内存存储空间的。
  • 进程创建的过程
    • 复制进程的描述符,一一复制其他进程的资源(采用写时复制技术),分配子进程的内核堆栈并对内核堆栈关键信息进行初始化。
    • Linux创建一个新的进程是从复制开始的,在系统内核里首先是将父进程的进程控制块PCB进行拷贝,然后再根据自己的情况修改相应的参数,获取自己的进程号,再开始执行。
  • 进程创建过程中的重要函数或数据结构:
    • do_fork():主要完成调用 copy_process() 复制父进程信息、获得pid、调用 wake_up_new_task 将子进程加入调度器队列等待获得分配CPU资源运行、通过clone_flags标志做一些辅助工作。
    • copy_process():主要完成调用 dup_task_struct 复制当前进程(父进程)描述符 task_struct 、信息检查、初始化、把进程状态设置为 TASK_RUNNING (此时子进程置为就绪态)、采用写时复制技术逐一复制所有其他进程资源、调用 copy_thread 初始化子进程内核栈、设置子进程pid等。
    • dup_task_struct():复制当前进程(父进程)描述符 task_struct 和 copy_thread 初始化子进程内核栈,为子进程分配好内核栈。
    • copy_thread():完成内核栈关键信息的初始化。
    • thread_info 结构:小型的进程描述符。通过task指针指向进程描述符。thread_info 结构由低地址到高地址增长。task_struct 结构中没有直接指向 thread_info 结构的指针,而是用一个 void 指针类型的成员表示,然后通过类型转换来访问 thread_info 结构。

通过实验跟踪分析进程创建的过程

删掉menu之后克隆一份新的,把test.c覆盖掉,在menu下面执行 make roofts 。

编译运行出来可以看到列表中增加了fork。下图是 MenuOS 的运行效果。执行fork可以看到父进程和子进程都输出信息。

启动gdb,把内核加载进来,连接到target remote 1234

在sys_clone、do_fork、dup_task_struct、copy_process、copy_thread、ret_from_fork处各设置断点。

继续执行,停到了 do_fork 位置,next

到 copy_process() 函数。继续执行

继续执行,到copy_thread:

涉及 system_call 的那段段汇编代码跟踪不到。

总结

1.在Linux中,fork()系统调用产生的子进程在系统调用处理过程中从何处开始执行?

从用户态空间来看,就是fork系统调用的下一条指令。

子进程和父进程都从调用fork函数的下一条语句开始执行

2.fork调用的特性“一次调用,两次返回”,它可能有三种不同的返回值:

1)在父进程中,fork返回新创建子进程的进程pid(返回值>0);

2)在子进程中,fork返回0;

3)如果出现错误,fork返回一个负值。

创建新进程成功后,系统中出现两个基本完全相同的进程,这两个进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略。此时,两个进程都从fork开始往下执行,只是pid不同。

3.父进程和新创建的子进程之间最大区别在于他们有着不同的PID。

4.所有的子进程是在do_fork实现创建和调用的。

5.对后面的跟踪状态还不太懂,等弄清楚了再进行补充。

参考资料:https://blog.csdn.net/zxm342698145/article/details/56513252

https://blog.csdn.net/Always2015/article/details/45008785?locationNum=9&fps=1

2019-2020-1 20199324《Linux内核原理与分析》第七周作业的更多相关文章

  1. 2019-2020-1 20199329《Linux内核原理与分析》第九周作业

    <Linux内核原理与分析>第九周作业 一.本周内容概述: 阐释linux操作系统的整体构架 理解linux系统的一般执行过程和进程调度的时机 理解linux系统的中断和进程上下文切换 二 ...

  2. 2019-2020-1 20199329《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 一.上周问题总结: 未能及时整理笔记 Linux还需要多用 markdown格式不熟练 发布博客时间超过规定期限 二.本周学习内容: <庖丁解 ...

  3. 20169212《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 这一周学习了MOOCLinux内核分析的第一讲,计算机是如何工作的?由于本科对相关知识的不熟悉,所以感觉有的知识理解起来了有一定的难度,不过多查查资 ...

  4. 20169210《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 本周作业分为两部分:第一部分为观看学习视频并完成实验楼实验一:第二部分为看<Linux内核设计与实现>1.2.18章并安装配置内核. 第 ...

  5. 2018-2019-1 20189221 《Linux内核原理与分析》第九周作业

    2018-2019-1 20189221 <Linux内核原理与分析>第九周作业 实验八 理理解进程调度时机跟踪分析进程调度与进程切换的过程 进程调度 进度调度时机: 1.中断处理过程(包 ...

  6. 2017-2018-1 20179215《Linux内核原理与分析》第二周作业

    20179215<Linux内核原理与分析>第二周作业 这一周主要了解了计算机是如何工作的,包括现在存储程序计算机的工作模型.X86汇编指令包括几种内存地址的寻址方式和push.pop.c ...

  7. 2019-2020-1 20209313《Linux内核原理与分析》第二周作业

    2019-2020-1 20209313<Linux内核原理与分析>第二周作业 零.总结 阐明自己对"计算机是如何工作的"理解. 一.myod 步骤 复习c文件处理内容 ...

  8. 2018-2019-1 20189221《Linux内核原理与分析》第一周作业

    Linux内核原理与分析 - 第一周作业 实验1 Linux系统简介 Linux历史 1991 年 10 月,Linus Torvalds想在自己的电脑上运行UNIX,可是 UNIX 的商业版本非常昂 ...

  9. 《Linux内核原理与分析》第一周作业 20189210

    实验一 Linux系统简介 这一节主要学习了Linux的历史,Linux有关的重要人物以及学习Linux的方法,Linux和Windows的区别.其中学到了LInux中的应用程序大都为开源自由的软件, ...

  10. 2018-2019-1 20189221《Linux内核原理与分析》第二周作业

    读书报告 <庖丁解牛Linux内核分析> 第 1 章 计算工作原理 1.1 存储程序计算机工作模型 1.2 x86-32汇编基础 1.3汇编一个简单的C语言程序并分析其汇编指令执行过程 因 ...

随机推荐

  1. 吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring框架的基本思想

    EJB的学习成本很高,开发效率却不高,需要编写很多重复的代码,这些问题阻止了EJB的继续发展.就在EJB技术止步不前的时候,Spring框架在合适的时机出现了,Spring框架和EJB不同,Sprin ...

  2. redis(三)----连接池配置

    1. 目录结构: 2. 测试源码 package com.redis; import redis.clients.jedis.Jedis; import redis.clients.jedis.Jed ...

  3. C++ 一个exe的两个运行实例之间共享数据

    #pragma data_seg("Shared") volatile int iNum = 0; #pragma data_seg() #pragma comment(linke ...

  4. JS-语句三

    关于if语句的几个练习: 1. 输入三个整数,x,y,z,最终以从小到大的方式输出.  思路:先列举出每种可能,然后做if套嵌.        var x = prompt("请输入一个数字 ...

  5. C++交换两个变量值的方法

    简单地列一下交换两个变量值地几种方法. 1.通过第三方实现,这一种也是最最最常见普通的方法: void swap(int *a, int *b) { int tmp = *a; *a = *b; *b ...

  6. kaggle——TMDB 电影票房收入预测

    介绍 看电影是目前人们休闲娱乐,消遣时光的选择之一.我们都知道,有些电影的票房很高,有的电影票房却很低,那么决定票房的因素是什么呢?本次将介绍,如何根据电影上映前的一些信息来预测出该电影的票房. 知识 ...

  7. Java并发分析—ConcurrentHashMap

    LZ在 https://www.cnblogs.com/xyzyj/p/6696545.html 中简单介绍了List和Map中的常用集合,唯独没有CurrentHashMap.原因是CurrentH ...

  8. IO读写

    1.read & write read: 把数据从内核缓冲区复制到进程缓冲区. write: 把数据从进程缓冲区复制到内核缓冲区. 上层程序的IO操作.不是物理设备级别的读写,而是缓存的复制. ...

  9. MySQL学习笔记——〇六SQLAlchemy框架

    我们在前面所用的方法都是在可视化的视图软件或者terminal里直接写SQL语句来对数据库进行访问,这里我们大概讲一下一个新的框架——SQLAlchemy. OEM框架 OEM的概念 对象-关系映射( ...

  10. Java 语句while、do while、for循环、嵌套、for与while的区别、break continue(3)

    for循环语句,双从for嵌套: /* for(初始化表达式:循环条件表达式:循环后的操作表达式) { 执行语句: } */ /*1,变量有自己的作用域.对于for来讲:如果将用于控制循环的增量定义在 ...