2017-2018-1 20179205《Linux内核原理与设计》第七周作业
《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内核原理与设计》第七周作业的更多相关文章
- 2017-2018-1 20179205《Linux内核原理与设计》第九周作业
<Linux内核原理与设计>第九周作业 视频学习及代码分析 一.进程调度时机与进程的切换 不同类型的进程有不同的调度需求,第一种分类:I/O-bound 会频繁的进程I/O,通常会花费很多 ...
- 2017-2018-1 20179205《Linux内核原理与设计》第二周作业
<Linux内核原理与分析>第二周作业 本周视频学习情况: 通过孟老师的视频教程,大致对风诺依曼体系结构有了一个初步的认识,视频从硬件角度和程序员角度对CPU和Main Memory(内存 ...
- 20169212《Linux内核原理与分析》第二周作业
<Linux内核原理与分析>第二周作业 这一周学习了MOOCLinux内核分析的第一讲,计算机是如何工作的?由于本科对相关知识的不熟悉,所以感觉有的知识理解起来了有一定的难度,不过多查查资 ...
- 20169210《Linux内核原理与分析》第二周作业
<Linux内核原理与分析>第二周作业 本周作业分为两部分:第一部分为观看学习视频并完成实验楼实验一:第二部分为看<Linux内核设计与实现>1.2.18章并安装配置内核. 第 ...
- 2018-2019-1 20189221 《Linux内核原理与分析》第九周作业
2018-2019-1 20189221 <Linux内核原理与分析>第九周作业 实验八 理理解进程调度时机跟踪分析进程调度与进程切换的过程 进程调度 进度调度时机: 1.中断处理过程(包 ...
- 2017-2018-1 20179215《Linux内核原理与分析》第二周作业
20179215<Linux内核原理与分析>第二周作业 这一周主要了解了计算机是如何工作的,包括现在存储程序计算机的工作模型.X86汇编指令包括几种内存地址的寻址方式和push.pop.c ...
- 2019-2020-1 20199329《Linux内核原理与分析》第九周作业
<Linux内核原理与分析>第九周作业 一.本周内容概述: 阐释linux操作系统的整体构架 理解linux系统的一般执行过程和进程调度的时机 理解linux系统的中断和进程上下文切换 二 ...
- 2019-2020-1 20199329《Linux内核原理与分析》第二周作业
<Linux内核原理与分析>第二周作业 一.上周问题总结: 未能及时整理笔记 Linux还需要多用 markdown格式不熟练 发布博客时间超过规定期限 二.本周学习内容: <庖丁解 ...
- 2019-2020-1 20209313《Linux内核原理与分析》第二周作业
2019-2020-1 20209313<Linux内核原理与分析>第二周作业 零.总结 阐明自己对"计算机是如何工作的"理解. 一.myod 步骤 复习c文件处理内容 ...
- 2017-2018-1 20179205《Linux内核原理与设计》第四周作业
<Linux内核原理与分析> 视频学习及实验操作 Linux内核源代码 视频中提到了三个我们要重点专注的目录下的代码,一个是arch目录下的x86,支持不同cpu体系架构的源代码:第二个是 ...
随机推荐
- vue-cli2使用cdn方式引入cytoscape
1. index.html头部引用 <script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.2.19/cytos ...
- 再看perf是如何通过dwarf处理栈帧的
从结构体stack_dump入手, util/unwind-libunwind-local.c 中有函数access_mem #0 access_mem (as=0x1f65bd0, addr=140 ...
- 【bzoj5108】[CodePlus2017]可做题 拆位+乱搞
题目描述 给出一个长度为 $m$ 的序列 $a$ ,编号为 $a_1\sim a_m$,其中 $n$ 个位置的数已经确定,剩下的位置的数可以任意指定.现在令 $b$ 表示 $a$ 的前缀异或和,求 $ ...
- Java基础之开关语句详解
switch 语句是单条件多分支的开关语句,它的一般格式定义如下(其中break语句是可选的): switch(表达式) { case 常量值: 若干个语句 break; case 常量值: 若干个 ...
- NYOJ 1000 又见斐波那契数列
描述 斐波那契数列大家应该很熟悉了吧.下面给大家引入一种新的斐波那契数列:M斐波那契数列. M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = a F[1] = b F[n] = F[ ...
- [牛客练习赛29D]禁止动规
description newcoder 你在一个无限长的数轴上,一开始你在原点 本来你只有两种操作:向左dp,以及向右dp 然而由于禁止dp 于是你只能另寻出路 万幸的是,dp之神随机给了你n个变量 ...
- 搞笑的代码 ( funny )
搞笑的代码 ( funny ) 在OI界存在着一位传奇选手——QQ,他总是以风格迥异的搞笑代码受世人围观 某次某道题目的输入是一个排列,他使用了以下伪代码来生成数据 while 序列长度<n d ...
- 【BZOJ 3569】DZY Loves Chinese II 随机化+线性基
用到一个结论——[先建树,再给每个非树边一个权值,每个树边的权值为覆盖他的非树边的权值的异或和,然后如果给出的边存在一个非空子集异或和为0则不连通,否则连通](必须保证每条边的出现和消失只能由自己产生 ...
- python基础之魔法方法
由于hexo自带的markdown渲染引擎对双下划线做了转义,在正文中看到的魔法方法前后都没有双下划线 setattr.getattr.delattr 可以拦截对对象属性的访问 setattr函数是用 ...
- 关于notepad++如何自动补全标签的问题
转自:https://blog.csdn.net/Panda_Eyes1/article/details/81486331 关于notepad++如何自动补全标签的问题 2018年08月07日 18: ...