2018-2019-1 20189213《Linux内核原理与分析》第四周作业

《Linux内核原理与分析》第四周学习总结:

1.课本知识总结:

本章内容并不多,首先是介绍了一些Linux内核源代码的目录结构,并基于Linux内核源代码构造一个简单的操作系统MenuOS,同时在MenuOS启动过程中跟踪分析Linux内核的启动过程。
操作系统的“两把宝剑”:中断上下文、进程上下文。其中中断上下文的切换主要用来保存现场和恢复现场,而进程上下文实际上是进程执行活动全过程的静态描述。
书中所描述的一切内容都是基于Linux内核3.18.6版本,其中Linux内核源码的目录包括以下这些:
1508946-20181101210549697-123941800.png
其中我们主要关注arch目录,因为它里面存放了许多CPU体系结构的相关代码;
当然也有几个比较关键的目录:
block: 存放Linux存储体系中关于块设备管理的代码;
crypto:存放常见的加密算法的C语言代码;
init(初始化):存放Linux内核启动时的初始化代码;
ipc目录:存放Linux支持的IPC(进程间通信)的代码实现;
kernel:存放内核本身需要的一些核心代码文件;等等。

2.构造一个简单的Linux内核:

由于实验是在实验楼上进行的,已经搭好了环境,所以不再过多进行描述。
这里主要讲如何在自己的虚拟机搭环境,构建一个简单的Linux内核:
首先是进行Linux3.18.6内核版本的下载,下载好后编译并运行,虽然等待时间很长,但自己动手做一遍觉得会有不同的收获。
1508946-20181102091709994-1823017128.png
1508946-20181102092819254-807204118.png
运行后我们可以进行根文件系统的制作,这样就可以启动不带调试信息的Linux内核和MenuOS了:
1508946-20181102093146464-2033945906.png
1508946-20181102141128862-1194984527.png

3.重点实验:跟踪分析Linux内核的启动过程

虽然实验对照书上内容看操作并不难,但理解起来确实蛮难的。
第一步:使用gdb跟踪调试内核,首先命令中有-s与-S参数的加入:
-S:freeze CPU at startup (use ’c’ to start execution) 在系统启动的时候冻结CPU,使用c键继续执行后续操作;
-s:shorthand for -gdb tcp::1234 打开远程调试端口,默认使用tcp协议1234端口,若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项 。
这个指令的作用是在开始的时候就让CPU停止在启动的那一刻,我们可以看到如下的界面:
1508946-20181101212152980-1978890583.png

第二步:再打开一个窗口,水平分割,启动gdb,把内核加载进来,建立连接,并设置相应断点加用‘c’运行:
1508946-20181101212015854-494135872.png
1508946-20181101212042520-345714475.png

第三步:对内核启动的有关分析:
(1)start_kernel()
main.c 中没有 main 函数,start_kernel() 相当于是C中的main函数。start_kernel是一切的起点,在此函数被调用之前内核代码是用汇编语言写的,完成系统的初始化工作,为c代码的运行设置环境。由调试可得 start_kernel 在500行:
1508946-20181101212723287-867386649.png
(2)init_task()
start_kernel() 函数几乎涉及到了内核的所有模块,如:trap_init()(中断向量的初始化)、mm_init()(内存管理的初始化)sched_init()(调度模块的初始化)等,首先是510行的init_task():
1508946-20181101213019169-335394810.png
可以看出 init_task(0号进程)是 task_struct 类型,是进程描述符,使用宏INIT_TASK对其进行初始化。接下来就是对各种模块的初始化。
(3)rest_init()
通过rest_init()新建kernel_init、kthreadd内核线程:
1508946-20181101213140728-1762215240.png
在403行代码中调用 kernel_thread()创建1号内核线程(在 kernel_init 函数正式启动)。
这里对比一下init_task 和 kernel_thread():
1508946-20181101213422578-1336122990.png
kernel_thread()是 fork 出了一个新进程来执行kernel_init 函数,而 init_task 是使用宏进行初始化的。也就是说0进程不是系统通过 kernel_thread 的方式(也就是 fork)创建的(init_task 是唯一一个没有通过 fork()产生的进程)。
在405行代码中调用 kernel_thread()执行 kthreadd函数,创建 PID=2的内核线程:
1508946-20181101220652268-1467706124.png
kthreadd函数的任务是管理和调度其他内核线程 kernel_thread。for 循环中运行 kthread_create_list 全局链表中维护的 kthread, 在create_kthread()函数中,会调用 kernel_thread 来生成一个新的进程并被加入到此链表中,因此所有的内核线程都是直接或者间接的以 kthreadd 为父进程。

总结:
(1)init_task()(PID=0)在创建了init进程后,调用 cpu_idle() 演变成了idle进程,执行一次调度后,init进程运行;
(2)1号内核线程负责执行内核的部分初始化工作及进行系统配置,最后调用do_execve执行 init 函数,演变成 init 进程(用户态1号进程),init 进程是内核启动的第一个用户级进程;
(3)kthreadd(PID=2)进程由0号进程创建,始终运行在内核空间, 负责所有内核线程的调度和管理 。

4.个人理解分析及遇到的一些问题:

上述描述的基本都是书上的内容,比较官方也比较难理解。本章内容不多,操作难度也不大,但理解难度很大。
首先,几乎所有的内核模块均会在start_kernel进行初始化。在start_kernel中,会对各项硬件设备进行初始化,包括一些page_address、tick等等,直到最后需要执行的rest_init中,会开始让系统跑起来。
那么,rest_init这个过程中,会调用调用kernel_thread来创建内核线程kernel_init,它创建用户的init进程,初始化内核,并设置成1号进程,这个进程会继续做相关的系统初始化;
然后,start_kernel会调用kernel_thread并创建kthreadd,负责管理内核中得所有线程,然后进程ID会被设置为2;
最后,会创建idle进程(0号进程),不能被调度,并利用循环来不断调号空闲的CPU时间片,并且从不返回。

问题:
(1)本章学习中遇到了许多陌生的指令和术语,一边操作过程中一边查阅有关资料,但对有些术语还是不太理解。
(2)在自己虚拟机上搭建环境时,Linux-3.18.6内核版本根据书中链接进行下载网速太慢,于是便在Linux官网上进行下载然后解压运行。
(3)“gcc -o init linktable.c menu.c test.c -m32 -static –lpthread”执行这句话的时候gcc报错出现:找不到lpthread?

转载于:https://www.cnblogs.com/aiYY/p/9892889.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/426518.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matlab窗函数带通滤波器,Matlab结合窗函数法设计数字带通FIR滤波器

Matlab结合窗函数法设计数字带通FIR滤波器 课程设计任务书学生姓名: 专业班级: 通信工程 指导教师: 工作单位: 信息工程学院 题 目:利用 Matlab 仿真软件系统结合窗函数法设计一个数字带通 FIR 滤波器初始条件: 1.《数…

java学习(53):接口的定义和创建

定义一个computer类 package com.company; public interface computer{ /定义公告,静态,常量/ public static final int MAX_NUM5000; /接口中只允许定义公共的抽象方法/ public abstract double couunt(double num1,double num2,char tag); } 定义一个…

PHP动态设计的设计流程,《PHP设计模式介绍》第十四章 动态记录模式

到目前为止,您所看到的这些设计模式大大提高了代码的可读性与可维护性。然而,在WEB应用设计与开发中一个基本的需求与挑战:数据库应用,这些设计模式都没有涉及到。本章与接下来的两章—表数据网关与表数据映射,提供了三…

java学习(54):接口之间的继承

定义一个接口类 //接口 interface interface4 { public abstract void fly(); public abstract void eat(); } //定义一个老鹰类 public class interface3 implements interface4{ public void fly(){ System.out.println(“我是老鹰,我会飞”); } public void eat…

php addall,深入解析thinkphp中的addAll方法

原因:在做中控系统中遇到了一个给用户批量分配角色的问题,刚开始想到的是循环插入,但立马给否定了,循环操作数据库开发者的大忌啊,于是查找手册找到数据写入看到批量操作:addAll(),测试成功,以为…

Java排查问题随笔

常言道:“好记性不如烂笔头”,确实很有道理。在日常工作中,偶尔处理下线上问题还是很常见的,经常出现的情况就是忘记一些常用命令(套路)的用法了,因此整理下来非常用必要,以便关键时…

java学习(55):定义一个抽象类的继承

不同的是定义一个抽象类先 //抽象类 public abstract class interface4 { public abstract void fly(); public abstract void eat(); } //定义老鹰类继承 /定义一个老鹰类 public class interface3 extends interface4{ public void fly(){ System.out.println(“我是老鹰&…

可持久化线段树学习笔记

可持久化线段树,即主席树。 每次修改的时候不修改原来的节点,暴力建新节点,充分运用了函数式编程的思想。 模板题:给定一个数列,\(m\) 次询问求区间 \([l,r]\) 内的第 \(k\) 大。 利用前缀和思想: #include…

wordpress functions.php 在哪,在functions.php中定义变量并在WordPress中的函数钩子中访问它们...

我想更详细地了解Wordpress结构.正如我所知,使用全局关键字并不是一个好主意.这是我想要完成的:Inside functions.php$affID 12334; //defining a variableadd_shortcode(affiliate_link, function() {$newLink https://example.com?id . $affID;return $newLink…

java学习(56):接口之间的继承续

//定义一个接口,里面放置多个方法 public interface CountManagement { double count(double n,double m,char tag); double count(double up,double down,double h); double eqAax(double num1,double num2); } //定义一个接口,里面需要实现多个方法 pu…

[UE4]单机游戏改网络游戏,不完全清单

把Actor的复制打开中腰数据的复制打开,且只在服务器修改(比如角色属性血量)需要同步的Actor,不在客户端Spawn客户端的操作,先报告到服务器,服务器再广播到所有客户端某些逻辑只在服务器运行(比如…

java学习(57):内部类

/** 2 * 1.内部类可以直接访问外部类的成员,包括私有 3 * 2.外部类要访问内部类的成员必须创建对象 4 * author jjz 5 * 6 */ public class outer { //外部定义的方法 public void play(){ System.out.println(“我喜欢打篮球”); } public static void main(String…

php对接ai图片处理,php – 使用imagick将.psd和.ai转换为PNG / JPG

我解决了它,并将与世界分享!它会将.ai,.psd,.jpg,.png,.gif转换为缩略图.这是一个需要4个参数的函数:$dir – 要保存的目录.$tmpName – 命名不包括扩展名的文件的名称.$fileType – 自解释.$size – 大或小.function thumbGenerator($dir,$tmpName,$fil…

python初识

1.python的简介   python是一门解释型,弱类型 高级开发编程语言. 2.python安装 (1)python3.x  https://www.python.org/downloads/ (2)pycharm  https://www.jetbrains.com/pycharm/ 3、编写第一个python程序 符号:英文 编码方式:“utf-8…

java学习(58):私有内部类后访问

私有化外部方法访问 public class outer { //外部定义的方法 private class student { public void play() { System.out.println(“只有学生才会喜欢打篮球”); } } public void teacher() { student stu new student(); stu.play(); } public static void main(String[] arg…

java学习(59):static修饰内部类

class Outer { private int num 10; private static int num2 100; //内部类用静态修饰是因为内部类可以看出是外部类的成员public static class Inner {public void show() {//System.out.println(num);System.out.println(num2);}public static void show2() {//System.out…

Python_自定义关键字的使用

1.在Python中新建一个套件MOSAPP(一般为APP名称):New Suite→Directory 2.在套件下新建个资源文件My:New Resource:My 3.在My资源文件库下新建个关键字Mytest:New User KeyWord:Mytest 4.在01smoke下新建一…

php http请求xml数据,使用php从HTTP POST请求中检索XML

我检查了类似的问题但没有解决我面临的问题.我正在构建一个Web服务,我想从HTTP POST请求中检索XML数据,操纵数据并返回响应.编写脚本时应考虑以下信息:The communication mode is HTTP POST (not SOAP)The content type is text/xml.The POST request will contain …

java学习(60):java最终类(了解)

最终类 使用关键字 final 对类进行修饰. [访问控制符] final class 类名 { 类体} 例如: public final class MyClass{ ... } 说明: final 不能当做父类, 不能被继承,不能有子类 , 只能被实例化对象 . 如果认为封装类中的某些数据(成员变量) 或者 某些方法(成员方法) 不能…

Lesson 028 —— python 模块

Lesson 028 —— python 模块 在前面的几个章节中我们脚本上是用 python 解释器来编程,如果你从 Python 解释器退出再进入,那么你定义的所有的方法和变量就都消失了。 为此 Python 提供了一个办法,把这些定义存放在文件中,为一些脚…