《Linux内核分析》 第6周

一、进程的描述

1.进程控制块PCB

2.linux下的进程转化图

  • TASK_RUNNING可以是就绪态或者执行态,具体取决于系统调用

  • TASK_ZOMBIE僵尸进程(终止的进程)

3.进程描述符task_struct

    • task_struct是一个数据结构,数据结构庞大;
    • pid:进程标识值,一个int型数值
  1. 进程链表struct list_head tasks,数据结构如下:
  • 它是一个双向链表,用来把当前所有进程用链表连起来

  1. 进程描述符中有几个域表示父子关系
  • 程序创建的进程具有父子关系在编程时经常需要用到这样的父子关系。进程描述符中有几个域用来表示这样的关系。

  • 每个进程都有一个父进程,每一个父进程都有0个或多个子进程

  1. struct thread_struct thread
  • 与CPU相关

  1. struct *file表示打开的文件链表
  2. Linux为每个进程分配一个8k大小的内存区域,用于存放该进程两个不同的数据结构:Thread_info和进程的内核堆栈

二、进程的创建

1.复习:“道生一,一生二”

  • start_kernel创建了cpu_idle,即0号进程
  • 0号进程又创建了两个线程kernel_init和kthreadd
  • kernel_init即1号进程,这个进程最终启动了用户态

2.系统调用回顾

  1. 系统调用
  • 用户态int 0x80指令实现软中断,过程详细如图:

  1. fork与系统调用相关,如图:

3.创建新进程的过程理解

  1. 创建一个新进程的框架
  • dup——thread复制父进程的pcb

  • copy_process修改复制的pcb以适应子进程的特点,也就是子进程的初始化

  • 分配一个新的内核堆栈(用于存放子进程数据)

     - 内核堆栈的一部分也要从父进程中拷贝
    - ![](http://images2015.cnblogs.com/blog/744616/201603/744616-20160328214201832-60467643.png)
    - ![](http://images2015.cnblogs.com/blog/744616/201603/744616-20160328214217316-1809241664.png)
    - 根据拷贝的内核堆栈情况设置eip,esp寄存器的值
  1. 一个新进程(子进程)从哪一行代码开始执行?
  • 与之前写过的my_kernel相比较,kernel中可以指定新进程开始的位置(通过eip)。fork中也有相似的机制。
  • copy_thread in copy_process
1.*childregs = *current_pt_regs(); //复制内核堆栈,并不是全部,只是regs结构体(内核堆栈栈底的程序)
2.childregs->ax = 0; //为什么子进程的fork返回0,这里就是原因!
3.
4.p->thread.sp = (unsigned long) childregs; //调度到子进程时的内核栈顶
5.p->thread.ip = (unsigned long) ret_from_fork; //调度到子进程时的第一条指令地址,也就是说返回的就是子进程的空间了

4.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) //pid == 0和下面的else都会被执行到(一个是在父进程中即pid ==0的情况,一个是在子进程中,即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.}

三、实验 使用gdb跟踪创建新进程的过程

1.在实验楼环境下的操作步骤

  1. 更新menu内核,然后删除test_fork.c以及test.c(以减少对之后实验的影响)

  2. 编译内核,可以看到fork命令

  3. 启动gdb调试,并对主要的函数设置断点

  4. 在MenuOS中执行fork,就会发现fork函数停在了父进程中

  5. 继续执行之后,停在了do_fork的位置。然后n单步执行,依次进入copy_process、dup_task_struct。按s进入该函数,可以看到*dst = *src(也就是复制父进程的struct)

  6. 在copy_thread中,把task_pg_regs(p)也就是内核堆栈特定的地址找到并初始化

四、总结

本周的课堂主要讲述的是进程的前半部分——关于基本的描述,以及新进程生命周期的开始(进程创建)。

关于进程描述,可以看到的是task_struct是进程描述的关键;其中含有一个进程从创建到终结的全部信息。关于进程创建,这里以fork函数为例进行了讲解;因为调用了fork函数之后就会创建新进程,创建的过程从代码和gdb调试两个方向进行了分析。

《Linux内核分析》 第六周的更多相关文章

  1. Linux内核及分析 第六周 分析Linux内核创建一个新进程的过程

    实验过程 1.github上克隆相应的mengning/menu.git 2.测试menuOS,测试fork直接执行结果 3.配置调试系统,进入gdb调试,利用file linux-3.18.6/vm ...

  2. 2019-2020-1 20199303 《Linux内核原理分析》 第一周作业

    2019-2020-1 20199303 <Linux内核原理分析> 第一周作业 1. 环境准备 在众多的Linux发行版中,Ubuntu,小红帽还有类Unix系统的BSD系统,我选择了目 ...

  3. Linux内核及分析 第八周 进程的切换和系统的一般执行过程

    学习笔记: 一.进程调度与进程调度的时机分析 1.不同类型的进程有不同需求的调度需求: 第一种分类: —I/O-bound:频繁的进行I/O,通常会花费很多时间等待I/O操作的完成 —CPU-boun ...

  4. Linux内核及分析 第七周 可执行程序的装载

    实验步骤 1. 更新menu,用test.c覆盖test_exec.c 2. 把init 和 hello 放到了rootfs.img目录下,执行exec命令的时候自动加载了hello程序 3. 执行e ...

  5. Linux内核及分析 第五周 扒开系统调用的三层皮(下)

    实验内容: 1.执行rm menu -rf命令,强制删除原有的menu 2.使用git命令 git clone https://github.com/mengning/menu.git 克隆新的men ...

  6. Linux内核及分析 第三周 Linux内核的启动过程

    实验过程: 打开shell终端,执行以下命令: cd LinuxKernel/ qemu -kernel linux-3.18.6/arch/x86/boot/bzImage-initrd rootf ...

  7. Linux内核读书笔记第六周

    主要内容: 什么是调度 调度实现原理 Linux上调度实现的方法 调度相关的系统调用 什么是调度 现在的操作系统都是多任务的,为了能让更多的任务能同时在系统上更好的运行,需要一个管理程序来管理计算机上 ...

  8. LINUX内核分析第六周学习总结——进程的描述与创建

    LINUX内核分析第六周学习总结--进程的描述与创建 标签(空格分隔): 20135321余佳源 余佳源 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc ...

  9. linux内核分析第六周学习笔记

    LINUX内核分析第六周学习总结 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.c ...

  10. LINUX内核分析第六周学习总结——进程的描述和进程的创建

    LINUX内核分析第六周学习总结——进程的描述和进程的创建 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/cours ...

随机推荐

  1. DevExpress04、LayoutControl、GalleryControl

    首先需求是通过LayoutControl控件设计下图所示的窗体: 从该界面的设计过程 1.向窗体中添加LayoutControl控件 在将该控件拖入窗体后,最好立即设置该控件的尺寸和位置.拖入后,在如 ...

  2. Java之Https请求

    import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import ...

  3. mysql 导出表数据表结构

    在命令行下mysql的数据导出有个很好用命令mysqldump,它的参数有一大把,可以这样查看: mysqldump 最常用的: mysqldump -uroot -pmysql databasefo ...

  4. JAVA框架 Spring 调用jdbcsuport简化开发

    一)使用DAO的jdbcsuport来简化开发 首先来清楚一个概念: 我们在进行配置文件来进行依赖注入的时候,主要是通过set方法来进行设置的. 正常我们使用spring的jdbctemplate的时 ...

  5. day71

    上节回顾:(模板层) 1 模板之变量---{{ }}   -支持数字,字符串,布尔类型,列表,字典---相当于对它进行了打印   -函数--->相当于加括号运行(不能传参数)   -对象---& ...

  6. TClientDataSet 提交时提示 Field value Required 但是未提示具体哪个字段。

    TClientDataSet 提交时提示 Field value Required 但是未提示具体哪个字段. 这个错误特别麻烦,要使用 midas 控件时,虽然很方便.但是出错了根本找不到原因,特别是 ...

  7. Python3入门(一)——概述与环境安装

    一.概述 1.python是什么 Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言. Python 是一种解释型语言: 这意味着开发过程中没有了编译这个环节.类似于PHP和 ...

  8. WFP page navigator control

    WPF navigator UI: <Grid x:Class="WpfApplication2.PagerNav" xmlns="http://schemas.m ...

  9. 使用Fortify进行代码静态分析(系列文章)

    BUG级别:低 Code Correctness(代码正确性) 1.Class does not Implement Equals(类未能实现Equals方法) Dead Code(死亡代码) 1.U ...

  10. POJ1080

    一道字符串DP,然而不需要状压之类的玄学操作 题目大意:给你两个串,由'A','C','G','T'组成,现在你可以在这两个串中的某些位置插入'-',最终要使得它们的长度相等 给出两个字符匹配时的匹配 ...