《Linux内核原理与设计》第七周作业

视频学习及操作分析

创建一个新进程在内核中的执行过程 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();函数返回了两次,即在父子进程中各返回一次,父进程从系统调用中返回比较容易理解,子进程从系统调用中返回,那它在系统调用处理过程中的哪里开始执行的呢?这就涉及子进程的内核堆栈数据状态和task_struct中thread记录的sp和ip的一致性问题,这是在哪里设定的?copy_thread in copy_process

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; //调度到子进程时的第一条指令地址 int copy_thread(unsigned long clone_flags, unsigned long sp,
unsigned long arg, struct task_struct *p)
{ struct pt_regs *childregs = task_pt_regs(p);
struct task_struct *tsk;
int err; p->thread.sp = (unsigned long) childregs;
p->thread.sp0 = (unsigned long) (childregs+1);
memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); if (unlikely(p->flags & PF_KTHREAD)) {
/* kernel thread */
memset(childregs, 0, sizeof(struct pt_regs)); p->thread.ip = (unsigned long) ret_from_kernel_thread; //如果创建的是内核线程,则从ret_from_kernel_thread开始执行
task_user_gs(p) = __KERNEL_STACK_CANARY;
childregs->ds = __USER_DS;
childregs->es = __USER_DS;
childregs->fs = __KERNEL_PERCPU;
childregs->bx = sp; /* function */
childregs->bp = arg;
childregs->orig_ax = -1;
childregs->cs = __KERNEL_CS | get_kernel_rpl();
childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_FIXED;
p->thread.io_bitmap_ptr = NULL;
return 0;
} *childregs = *current_pt_regs();//拷贝已有内核堆栈数据和制定新进程的第一条指令地址 childregs->ax = 0; //子进的程返回值是0
...
p->thread.ip = (unsigned long) ret_from_fork;//ip指向 ret_from_fork,子进程从此处开始执行
task_user_gs(p) = get_user_gs(current_pt_regs());
...
return err;

使用GDB跟踪创建新进程的过程

可以看到执行结果如上,输入fork输出了一个父进程一个子进程。接下来要使用gdb来跟踪调试进程创建过程,所以需要设置断点。若执行成功,那么可以分别在sys_clone,do_fork,dup_task_struct,copy_process,copy_thread,ret_from_fork这几处设置断点,这是执行一个fork可以看到停在Fork a new process处。按c继续执行:

下面出现了copy_process

task_struct结构关系

struct task_stuct数据结构和庞大,linux进程的状态操作与操作系统原理中的描述状态似乎有所不同,比如TASK_RUNNING既可以表示就绪状态也可以表示运行状态。

问题与分析



在实验过程中出现了打不开'initrd'的情况,反复在LinuxKernel和menu目录下尝试几次,结果失败,上网未查到答案,没有解决。

教材十一章、十二章学习

1、时间管理在内核中占有很重要的地位,内核中有大量的函数都是基于时间驱动的。事实上内核必须在硬件的帮助之下节拍才能计算和管理时间。硬件为内核提供了一个系统定时器用来计算流逝的时间。系统定时器以某种频率自行触发(也称为“射中” 或 “击中” 时钟中断),该频率可以通过编程预定,称作节拍率。(内核连续两次时钟中断的间隔时间称为节拍,它等于节拍率分之一)当时钟中断发生时,内核就通过一种特殊的中断处理程序对其进行处理。

2、利用时间中断周期执行的工作:

更新系统运行时间;跟新实际时间;在smp系统中均衡调度各处理器的运行列队;检查当前进程是否用尽了时间片,如果用尽则重新进行调度;运行超时的动态定时器;更新资源消耗和处理器时间的统计值。

3、系统定时器的频率(节拍率)是静态预处理定义的。HZ越高的优势:内核定时器以更高的频度和准确度执行;提高运行的精度;对资源消耗和系统运行时间等的测量有更精细的解析度;进程抢占更准确。劣势:节拍率越高,时钟中断程序占用处理器时间越多;并且频繁打乱处理器cache并增加耗电。无时钟OS可以根据系统的空闲程度动态改变频率;全局变量jiffies 用来计算自系统启动以来产生的节拍总数,启动时内核将该初始变量设置为0 ,然后每次时钟中断处理程序会增加这个值.

4、时钟中断处理程序:

就是每次发生时钟中断后,需要执行的程序,类似于中断处理程序,已经注册到内核中了,这个程序一般会完成以下的一些工作:获得 xtime_lock 锁,以便对访问 jiffies_64 和墙上时间 xtime 进行保护;需要时应答或重新设置系统时钟;周期性的使用墙上时间更新实时时钟;调用系统结构无关的时钟例程: tick_periodic()。

5、定时器并不周期运行,动态定时器就是不断的创建和撤销,它的生命周期一般会经历一下几个步骤:

6、内存最基本的管理是页,同时按照内存地址的大小,大致分为3个区;页是内存管理的最小单元,但是并不是所有的页对于内核都一样,内核将内存按地址的顺序分成了不同的区,有的硬件只能访问有专门的区。一般DMA使用的页物理内存<16MB,分配ZONE_DMA区内存;正常可寻址的页物理内存16~896MB,分配ZONE_NORMAL区内存;动态映射的页物理内存>896MB,分配ZONE_HIGHMEM区内存。linux中的高速缓存是用所谓 slab 层来实现的,slab层即为内核中管理高速缓存的机制。与单CPU环境不同,SMP环境下的并行是真正的并行。单CPU环境是宏观并行,微观串行。真正并行时,会有更多的并发问题。按CPU来分配数据主要有2个优点:最直接的效果就是减少了对数据的锁,提高了系统的性能;由于每个CPU有自己的数据,所以处理器切换时可以大大减少缓存失效的几率。如果一个处理器操作某个数据,而这个数据在另一个处理器的缓存中时,那么存放这个数据的那个处理器必须清理或刷新自己的缓存。持续的缓存失效成为缓存抖动,对系统性能影响很大。

7、在众多的内存分配函数中,如何选择合适的内存分配函数很重要,下面总结了一些选择的原则:如果需要物理上连续的页,选择低级页分配器或者 kmalloc 函数;如果kmalloc分配是可以睡眠的,指定 GFP_KERNEL标志;如果kmalloc分配是不能睡眠的,指定 GFP_ATOMIC标志;如果不需要物理上连续的页,vmalloc函数;如果需要高端内存,alloc_pages 函数获取page的地址,在用kmap之类的函数进行映射;如果频繁撤销/创建教导的数据结构,建立slab高速缓存。

2017-2018-1 20179205《Linux内核原理与设计》第七周作业的更多相关文章

  1. 2017-2018-1 20179205《Linux内核原理与设计》第九周作业

    <Linux内核原理与设计>第九周作业 视频学习及代码分析 一.进程调度时机与进程的切换 不同类型的进程有不同的调度需求,第一种分类:I/O-bound 会频繁的进程I/O,通常会花费很多 ...

  2. 2017-2018-1 20179205《Linux内核原理与设计》第二周作业

    <Linux内核原理与分析>第二周作业 本周视频学习情况: 通过孟老师的视频教程,大致对风诺依曼体系结构有了一个初步的认识,视频从硬件角度和程序员角度对CPU和Main Memory(内存 ...

  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 20199329《Linux内核原理与分析》第九周作业

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

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

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

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

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

  10. 2017-2018-1 20179205《Linux内核原理与设计》第四周作业

    <Linux内核原理与分析> 视频学习及实验操作 Linux内核源代码 视频中提到了三个我们要重点专注的目录下的代码,一个是arch目录下的x86,支持不同cpu体系架构的源代码:第二个是 ...

随机推荐

  1. [C/C++] const用法详解

    const在C语言中算是一个比较新的描述符,我们称之为常量修饰符,意即其所修饰的对象为常量(immutable). 我们来分情况看语法上它该如何被使用. 1.函数体内修饰局部变量.例:void fun ...

  2. 操作 使用XML的方法

    XmlHelper是一个工具类 public static class XMLHelper { /// <summary> /// XML的编码方式,默认是UTF-8 /// </s ...

  3. POJ1006:Biorhythms——题解

    http://poj.org/problem?id=1006 题目大意: 人生来就有三个生理周期,分别为体力.感情和智力周期,它们的周期长度为23天.28天和33天.每一个周期中有一天是高峰.在高峰这 ...

  4. android eclipse ndk使用记录

    为方便开发jni程序,android提供了ndk包来简化开发过程,避免开发人员下载完整的平台代码,并且可以在windows环境下集成到eclipse里面,大大加快了开发速度.这里记录下一个简单例子. ...

  5. poco入门

    源码按照poco.然后看README,进行安装. ./configure make make install #include "Poco/ActiveMethod.h" #inc ...

  6. STL之二:vector容器用法详解

    转载于:http://blog.csdn.net/longshengguoji/article/details/8507394 vector类称作向量类,它实现了动态数组,用于元素数量变化的对象数组. ...

  7. 使用Android Studio调试UiAutomator过程中遇到的问题

    声明: 这里纪录了个人学习和使用Android Studio调试UiAutomator过程中遇到遇到的问题,不定时进行更新,欢迎一起交流学习 1.Excution faild for task ‘:a ...

  8. git版本回退与撤销操作

    场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file. 场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步, ...

  9. Makefile的简单使用

    led.bin: led.o arm-linux-ld -Ttext 0x0 -o led.elf $^ arm-linux-objcopy -O binary led.elf led.bin arm ...

  10. 第01篇 说一下Setting,我一直没有讲过

        settings 调整 settings 中的设置是非常关键的,它们会改变 MyBatis 的运行时行为.下表描述了设置中各项的意图.默认值等. 设置参数 描述 有效值 默认值 cacheEn ...