20135130王川东

1、操作系统的三大管理功能包括:进程管理,内存管理,文件系统。

2、 Linux内核通过唯一的进程标识PID来区别每个进程。为了管理进程,内核必须对每个进程进行清晰的描述,进程描述符提供了内核所需了解的进程信息。每个进程的所有信息记录在了进程描述符(task_struct)中。struct  task_struct数据结构很庞大,包括进程状态、进程内核堆栈、进程打开的文件、进程优先级以及进程调度相关信息等等。这是一个包含了很多信息的结构体,也被称之为进程控制块(PCB)。

3、Linux中,PCB task_struct中不包含进程包含的线程列表信息。

4、Linux进程的状态与操作系统原理中的描述的进程状态似乎有所不同,比如就绪状态和运行状态都是TASK_RUNNING。这是因为在Linux中,所谓区别一个进程的状态是就绪还是运行,在于它是否得到了CPU的控制权。也就是说,这个进程是否在CPU上实际的执行,如果有实际执行,那就是运行,如果没有,哪怕目前是可以运行,也还只是就绪状态。

  注意,PCB task_struct中 存有进程链表,这是讲所有进程存在一个双向链表结构中。struct list_head tasks。

5、程序创建的进程具有父子关系,在编程时往往需要引用这样的父子关系。进程描述符中有几个域用来表示这样的关系。

6、Linux为每个进程分配一个8KB大小的内存区域,用于存放该进程两个不同的数据结构:Thread_info和进程的内核堆栈。进程处于内核态时使用, 不同于用户态堆栈,即PCB中指定了内核栈。内核控制路径所用的堆栈 很少,因此对栈和Thread_info 来说,8KB足够了

7、创建一个新进程在内核中的执行过程:fork、vfork和clone三个系统调用都可以创建一个新进程,而且都是通过调用do_fork来实现进程的创建;Linux通过复制父进程来创建一个新进程。从用户态的代码看fork();函数返回了两次,即在父子进程中各返回一次,父进程从系统调用中返回比较容易理解,子进程从系统调用中返回,那它在系统调用处理过程中的哪里开始执行的呢?Linux中,fork()系统调用产生的子进程在系统调用处理过程中从ret_from_fork处开始执行。

实验过程:

通过在myKernel中添加fork的功能,分析Linux内核创建一个新进程的过程。

添加后重新生成menu,并运行。

通过gdb调试,设置断点在sys_clone, do_fork, dup_task_struct, copy_process, copy_thread, ret_from_fork。运行menuOS中的fork,继续调试,查看断点处的代码情况

 创建新进程的过程分析:

创建的新进程是从哪里开始执行的:ret_from_fork
*childregs = *current_pt_regs();  复制内核堆栈(复制的pt_regs,是SAVE_ALL中系统调用压栈的那一部分。)

childregs->ax = 0; 子进程的fork返回0 p->thread.sp = (unsigned long) childregs; 调度到子进程时的内核栈顶
p->thread.ip = (unsigned long) ret_from_fork; 调度到子进程时的第一条指令地址

 ip指向的是ret_from_fork,所以是从这里开始执行的。

Linux操作系统通过start_kernel,在调用的时候执行得到cpu_idle进程,后来通过kernel_init和kthreadd生成了0号进程和1号进程,分别作为最初的内核进程和用户进程。这里的进程最初是通过程序员具体在代码中设置的结构啊,信息啊之类的,而之后的进程则是复制之前的进程,这里可以看做是父进程,生成了新的进程,也就是子进程,当然,子进程的信息会有修改,它并不是跟父进程完全一样。

程序调用状态可以表示为:

fork具体工作过程:

1. 调用sys_clone

2. 执行do_fork(), fork、vfork和clone三个系统调用都可以创建一个新进程,而且都是通过调用do_fork来实现进程的创建。do_fork()负责进程的复制。

3. 执行copy_process

4 dup_task_struct,复制父进程的task_struct信息到新的task_struct里

fork会产生父子进程,在父进程中,返回值是子进程的进程号;在子进程中,返回值为0。因此可通过返回值来判断当前进程是父进程还是子进程。使用fork函数得到的子进程是父进程的一个复制品,它从父进程处复制了整个进程的地址空间,包括进程上下文,进程堆栈,内存信息,打开的文件描述符,信号控制设定,进程优先级,进程组号,当前工作目录,根目录,资源限制,控制终端等。

5.copy_thread

6.ret_from_fork

进程的用户栈的起始地址存储在task_struct结构的stack_start成员中,新进程是从ret_from_fork处开始执行的。对于fork执行处理过程来说,父子进程共享同一段代码空间,”一次调用,两次返回“,其实对于调用fork的父进程来说,如果fork出来的子进程没有得到调度,那么父进程从fork系统调用返回。再看fork出来的子进程,由 copy_process函数可以看出,子进程的返回地址为ret_from_fork(和父进程在同一个代码点上返回),返回值直接置为0。所以当子进 程得到调度的时候,也从fork返回,返回值为0。ret_from_fork()调用schedule_tail()函数,用存放在栈中的值再装入所有寄存器,并强迫CPU返回到用户态。这样,eax寄存器就装过两个值,一个是子进程的值0,一个是父进程的值——子进程的PID。然后在fork()、vfork()或clone()返回时,新进程将开始执行。在不同的进程中返回不同的值。

《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. 复习宝典之Mysql数据库

    查看更多宝典,请点击<金三银四,你的专属面试宝典> 第一章:mysql数据库 1)mysql与mariaDb MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用 ...

  2. 记利用frp配合nginx实现内网透传

    frp下载 背景 : 内网有一台服务器A 在NAT背后 无法被其他客户端访问 借助公网服务器B来配置内网透传 即可通过B来访问A 服务端安装frps 启动: ./frps -c frps.ini 配置 ...

  3. 学习tp5的第三天(模型)

    一.模型 1.定义基础模型 <?php namespace app\index\model; use think\Model; class User extends Model{ // 设置完整 ...

  4. 获取当前目录下所有php文件内的函数名

    $dir = dirname(__FILE__); $files = scandir($dir); foreach($files as $name){ if($name == '.' || $name ...

  5. Python - 魔法字符串

    ''' #capitalize() ---首字母转换为大写--- s="sslssd" v=s.capitalize(); print(v) ''' ''' #center(20, ...

  6. python教程(六)·字符串

    我们已经学习了字符串的使用方法,我们还学习了使用索引和分片操作字符串,经历了这么长的时间,相信大家也有所掌握:本节将讨论并学习字符串的格式化与字符串的常用方法 字符串格式化 字符串是序列的一种,所以所 ...

  7. scala (5) 可变序列和不可变序列

    /** * 序列分为可变长和不可变长,序列其实就是list,底层是链表结构 * 特点:插入有序,可重复,增加和移除元素很快,查询慢 * 不可变长序列:List * 可变长序列:ListBuffer * ...

  8. 20155222 2016-2017-2 《Java程序设计》第9周学习总结

    20155222 2016-2017-2 <Java程序设计>第9周学习总结 教材学习内容总结 JDBC是用于执行SQL的解决方案,开发人员使用JDBC的标准接口,开发人员使用JDBC的标 ...

  9. 20155229--Java实验四《Android开发基础》

    20155229 Java实验四<Android开发基础> 实验内容: 任务一: Android Stuidio的安装测试: 参考<Java和Android开发学习指南(第二版)(E ...

  10. 2016-2017-2 20155325实验二《Java面向对象程序设计》实验报告

    实验二 面向对象程序设计-1 答案截图 码云代码链接 链接1 实验遇到的问题和解决过程 问题1:在plugins里搜索不到JUnitGenerator V2.0只能搜到Generste Teats 问 ...