本次实验过程如下:

1. 运行MenuOS系统

在实验楼的虚拟机环境里,打击打开shell,使用下面的命令

 cd LinuxKernel/
qemu -kernel linux-3.18./arch/x86/boot/bzImage -initrd rootfs.img

截图如下:

2. 使用 gdb 对 MenuOS 进行调试跟踪运行

1) 在命令行内输入如下代码:

 qemu -kernel linux-3.18./arch/x86/boot/bzImage -initrd rootfs.img -s -S # 关于-s和-S选项的说明:
// -S freeze CPU at startup (use ’c’ to start execution)
// -s shorthand for -gdb tcp::1234 若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项

效果如下:

2) 启动 gdb 并设置断点进行跟踪

gdb 中输入的代码如下:

 gdb
(gdb)file linux-3.18./vmlinux # 在gdb界面中targe remote之前加载符号表
(gdb)target remote: # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行
(gdb)break start_kernel # 断点的设置可以在target remote之前,也可以在之后

效果如下:

在 gdb 下,我们可以通过输入 c 命令来执行到断点位置,我们也可以通过输入 list 命令来查看接下来的几行代码。

以下是 gdb 的几个基本的调试命令:

kill [filename] 终止正在调试的程序
break [file:]function 在(file文件的)function函数中设置一个断点
clear 删除一个断点,这个命令需要指定代码行或者函数名作为参数
run [arglist] 运行您的程序 (如果指定了arglist,则将arglist作为参数运行程序)
bt Backtrace: 显示程序堆栈信息
print expr 打印表达式的值
continue 继续运行您的程序 (在停止之后,比如在一个断点之后)
list 列出产生执行文件的源代码的一部分
next 单步执行 (在停止之后); 跳过函数调用
set 设置变量的值。例如:set nval=54 将把54保存到nval变量中
step 单步执行 (在停止之后); 进入函数调用
watch 使你能监视一个变量的值而不管它何时被改变
Ctrl-C 在当前位置停止执行正在执行的程序,断点在当前行
finish 继续执行,直到当前函数返回
info [name] 查看name信息
return 强制从当前函数返回
make 使你能不退出 gdb 就可以重新产生可执行文件
help [name] 显示GDB命令的信息,或者显示如何使用GDB的总体信息
quit 退出gdb.

3. 实验总结

start_kernel() 中调用了一系列初始化函数,以完成kernel本身的设置。这些动作有的是公共的,有的则是需要配置的才会执行的。

start_kernel() 函数是内核的汇编与 C 语言的交接点,在该函数以前,内核的代码都是用汇编写的,完成一些最基本的初始化与环境设置工作。无论分析内核中的那一部分,都有些许的关联到 start_kernel() 函数。说到此,我们可以联想到 C 语言中的 main 函数,这个 start_kernel() 函数就有点类似于 main 函数,所有的命令都是从这里开始的。这段函数非常复杂,设计许许多多的方面,我们在此无法一一解读,所以只选择了一部分来解读。

在 start_kernel() 函数最后又一个 rest_init() 函数,这个函数是启动 init 进程( 所有进程的前导 )。

 asmlinkage __visible void __init start_kernel(void)
{
/*
...
*/
lockdep_init();
set_task_stack_end_magic(&init_task); // init_task即手工创建的PCB,0号进程即最终的idle进程。
smp_setup_processor_id();
/*
...
*/
trap_init(); // 中断初始化向量
mm_init(); // 内存管理莫怪的初始化
sched_init(); // 进程调度初始化
/*
...
*/
rest_init(); // 启动1号进程
}

init 进程是第一个 用户态 进程,叫做“1号进程”。它是通过 rest_init 函数中的 kernel_init 函数中的 run_init_process 生成,找根目录下的程序来作为“1号进程”。

当系统没有进程需要执行时就调用 idle 进程( 0号进程 )。从系统启动之后就一直存在。它创建了1号进程 kernel_init 和其他进程。这样系统就启动起来了。

总体来说,init_task 核心相当于一个 while(1) 的循环,当没有进程在运作时,0号进程在运作,在循环中它将会调用 schedule 函数以便在运行队列中有新进程加入时切换到该新进程上。

参考文献:

http://tech.ccidnet.com/art/302/20070705/1136127_1.html

作者:李若森

原创作品转载请注明出处

《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

使用gdb跟踪Linux内核启动过程(从start_kernel到init进程启动)的更多相关文章

  1. Linux内核分析-使用gdb跟踪调试内核从start_kernel到init进程启动

    姓名:江军 ID:fuchen1994 实验日期:2016.3.13 实验指导 使用实验楼的虚拟机打开shell cd LinuxKernel/ qemu -kernel linux-3.18.6/a ...

  2. 实验三:gdb跟踪调试内核从start_kernel到init进程启动

    原创作品转载请注明出处<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 如果我写的不好或者有误的地方请留言 ...

  3. 通过gdb跟踪Linux内核装载和启动可执行程序过程

    作者:吴乐 山东师范大学 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验目的:通过对一个简单的可执 ...

  4. LINUX内核分析第八周学习总结——进程的切换和系统的一般执行过程

    LINUX内核分析第八周学习总结——进程的切换和系统的一般执行过程 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/c ...

  5. 在qemu环境中用gdb调试Linux内核

    简介 对用户态进程,利用gdb调试代码是很方便的手段.而对于内核态的问题,可以利用crash等工具基于coredump文件进行调试.其实我们也可以利用一些手段对Linux内核代码进行gdb调试,qem ...

  6. 利用QEMU+GDB搭建Linux内核调试环境

    前言 对用户态进程,利用gdb调试代码是很方便的手段.而对于内核态的问题,可以利用crash等工具基于coredump文件进行调试. 其实我们也可以利用一些手段对Linux内核代码进行gdb调试,qe ...

  7. LINUX内核分析第六周学习总结——进程的描述和进程的创建

    LINUX内核分析第六周学习总结——进程的描述和进程的创建 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/cours ...

  8. LINUX内核分析第六周学习总结——进程的描述与创建

    LINUX内核分析第六周学习总结--进程的描述与创建 标签(空格分隔): 20135321余佳源 余佳源 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc ...

  9. Android系统启动流程(一)解析init进程启动过程

    整体流程大致如下:     1.init简介 init进程是Android系统中用户空间的第一个进程,作为第一个进程,它被赋予了很多极其重要的工作职责,比如创建zygote(孵化器)和属性服务等.in ...

随机推荐

  1. 如何让虚拟目录里面的webconfig不继承网站的设置

    在一个网站 中国红木网 下 建一个虚拟目录,结果虚拟目录系统会调用 中国红木网 上的web.config, 在网上找到以下解决方案 在(如根目录)所在的Web.config加上 如:<locat ...

  2. WPP

    WPP(Wavefront Parallel Processing) 上一行的第二个LCU处理完毕,即对当前行的第一个LCU的熵编码(CABAC)概率状态参数进行初始化,如图5所示.因此,只需要上一行 ...

  3. 鸟哥的Linux私房菜 第十八章、认识系统服务 (daemons)

    什么是 daemon 与服务 (service) Linux Daemon (守护进程)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些事件.它不需要用户输入就能运行 ...

  4. 小物件之radio单选列表

    有时候在控制器中做了一个数组 然后需要在模板view中循环 同时还需要判断是否有选中的值,就会造成很多开始闭合标签 以前都是这样写 这样实在太繁琐了,不如封装一个小物件 封装函数如下: 代码如下: f ...

  5. Linux中的文件压缩,打包和备份命令

    压缩解压命令 gzip  文件   -c : 将压缩数据输出到屏幕,可用来重定向 -v   显示压缩比等信息 -d   解压参数 -t    用来检验一个压缩文件的一致性看看档案有没错 -数字 : 压 ...

  6. Hibernate查询之Criteria查询

    转自:http://www.cnblogs.com/Laupaul/archive/2012/02/15/2353194.html Criteria是一种比hql更面向对象的查询方式.Criteria ...

  7. 后台action处理数据传递给前台界面

    package com.renmai.util; import java.io.IOException; import javax.servlet.http.HttpServletResponse; ...

  8. css控制文本框的只读属性的方法

    css 封装整个只读文本框的属性: .TextBoxReadOnly{ border:1px solid #C0C0C0; text-align:left; background-color:#D3D ...

  9. Java - 推断元音辅音

    随机生成字母, 推断是元音字母还是辅音字母. [0,26) + 偏移量'a'就能够生成小写字母. 代码: //: Main.java import java.util.Random; /** * 推断 ...

  10. VC++/MFC操作ini配置文件详解

    在我们写的程序当中,总有一些配置信息需要保存下来,以便完成程序的功能,最简单的办法就是将这些信息写入INI文件中,程序初始化时再读入.具体应用如下: 一.将信息写入.INI文件中. 1.所用的WINA ...