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

《庖丁解牛Linux内核分析》第三章

Linux内核源代码简介

使用cat /proc/version或uname -a命令,可以查看当前系统的Linux内核版本。

1800786-20191002152253957-1883151407.png

  • Linux内核源码目录结构

    • arch目录:与CPU体系结构相关的子目录列表

    • block目录:存放Linux存储体系中关于块设备管理的代码

    • crypto目录:存放常见的加密算法的C语言代码

    • drivers目录:驱动目录,里面分门别类地存放了Linux内核支持的所有硬件设备的驱动源代码

    • firmware目录:固件

    • fs目录:文件系统

    • include目录:存放公共的头文件

    • init:存放Linux内核启动时的初始化代码(lnit目录中的main.c源文件是整个Linux内核启动的起点,但它的起点不是main函数,是start_kernel函数。start_kernel函数是初始化Linux内核启动的起点。)

    • ipc目录:IPC是进程间通信,ipc目录里面是Linux支持的IPC的代码实现

    • kernel目录:kernel意思是内核,这个文件夹存放内核本身需要的一些核心代码文件,包括进程号pid等

    • lib目录:公用的库文件

    • mm目录:内存管理

构造一个简单的Linux内核

在“实验楼”虚拟机中,通过两个简单的命令就可以把Linux系统和一个简单的文件系统运行起来:


cd LinuxKernel/

qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img

1800786-20191003145822838-297184790.png

使用自己的Linux系统环境搭建MenuOS的过程

实验楼实验三

跟踪分析Linux内核的启动过程

使用实验楼的虚拟机打开shell


$ cd ~/LinuxKernel/

$ qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img

1800786-20191003172201628-10932937.png

内核启动完成后进入 menu程序,支持三个命令 help、version 和 quit。

1800786-20191003172255337-944967160.png

使用gdb跟踪调试内核


$ qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S 

/* 关于-s和-S选项的说明:

1. -S

 -S freeze CPU at startup (use ’c’ to start execution)

2. -s

-s shorthand for -gdb tcp::1234 

若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项 */

1800786-20191003173230131-1985328111.png

用上述命令启动内核,发现被冻结了。

再打开一个shell窗口,用Ctrl+Shift+O水平分割,启动gdb把内核加载进来,建立连接。


/* 打开 GDB 调试器 */

$ gdb

1800786-20191005103548413-378609944.png

在 GDB 中输入以下命令:


/* 在gdb界面中targe remote之前加载符号表 */

(gdb)file linux-3.18.6/vmlinux 

/* 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行 */

(gdb)target remote:1234

/* 断点的设置可以在target remote之前,也可以在之后 */

(gdb)break start_kernel 

1800786-20191005103930244-920052358.png

在start_kernel处设置断点,刚才是stop状态,如果按“c”继续执行,那么系统开始启动执行,启动到start_kernel函数的位置停在断点处,就可以看到start_kernel上下的代码。

1800786-20191005104042757-1058680148.png

再设置一个断点rest_init,继续执行,停在断点处,可以看到rest_init是在start_kernel的尾部进行调用的。


/* 在rest_init设置断点 */

(gdb)break rest_init 

/* 继续执行 */

(gdb)c 

1800786-20191005104254913-544610466.png

start_kernel()与init_task()/reat_init()中部分函数的分析

  • start_kernel():相当于C语言中的main函数,是一切的起点。完成了Linux内核的初始化工作。每个内核部件都是用这个函数进行初始化的。在start_kernel()开始执行之后会显示linux版本,除此之外,在init程序和内核线程执行的最后阶段还会显示很多其他信息。最后,就会在控制台上出现熟悉的登陆提示,通知用户Linux内核已经启动正在运行。

  • init_task():几乎涵盖了内核的所有主要模块,是唯一没有通过fork方式产生的进程,使用宏进行初始化。

  • rest_init():通过rest_init()新建kernel_init和kthreadd内核线程。

  • 其中各函数功能如下:

    • sched_init():初始化调度模块

    • build_all_zonelists():初始化内存管理

    • page_alloc_init():初始化伙伴系统分配程序

    • trap_init()、init_IRQ():初始化中断向量

    • mm_init():初始化内存管理模块

    • softing_init():软中断,初始化TASKLET_SOFTIRQ和HI_SOFTIRQ

    • time_init():初始化系统日期时间

    • kmem_cache_init():普通和高速缓存,初始化slab分配器

    • calibrate_delay():延迟函数,用于确定CPU时钟

    • kernel_thread():为进程1创建内核线程,这个内核线程又会创建其他的内核线程并执行/sbin/init程序。所有内核线程都是直接或间接地以kthreadd为父进程的

    • kthreadd():管理和调度其他内核线程kernel_thread

本周遇到的挫折

虽然之前说安了虚拟机,其实这个假期才开始配置。然而,在任何一个教程中都会一笔带过的VMware下载环节,我遭遇了很多挫折!!!看过了一个帖子总结的可能遇到的所有报错!!!其中,安装VM需要的vmnetbridge.dll在哪这个问题问了我无数遍。

后来我新的一轮下载中,给我们的VMware小朋友新建了个文件夹,不知为什么就好了。虽然这问题很傻没什么意义,但鉴于我终于按好了很开心,所以来这叨叨两句~

此为本人Linux学习第四周的内容,如有不足,还请批评指正,不胜感激。

以上

转载于:https://www.cnblogs.com/qianxiaoxu/p/11617468.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值