软件世界网 购物 网址 三丰软件 | 小说 美女秀 图库大全 游戏 笑话 | 下载 开发知识库 新闻 开发 图片素材
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
移动开发 架构设计 编程语言 Web前端 互联网
开发杂谈 系统运维 研发管理 数据库 云计算 Android开发资料
  软件世界网 -> 系统运维 -> linux内核启动过程追踪 -> 正文阅读

[系统运维]linux内核启动过程追踪

慕课18原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”
一、使用自己的Linux系统环境搭建MenuOS的过程
  # 下载内核源代码编译内核
  cd ~/LinuxKernel/
  wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.18.6.tar.xz
  xz -d linux-3.18.6.tar.xz
  tar -xvf linux-3.18.6.tar
  cd linux-3.18.6
  make i386_defconfig
  make # 一般要编译很长时间,少则20分钟多则数小时
  # 制作根文件系统
  cd ~/LinuxKernel/
  mkdir rootfs
  git clone https://github.com/mengning/menu.git  # 如果被墙,可以使用附件menu.zip
  cd menu
  gcc -o init linktable.c menu.c test.c -m32 -static –lpthread
  cd ../rootfs
  cp ../menu/init ./
  find . | cpio -o -Hnewc |gzip -9 > ../rootfs.img
  # 启动MenuOS系统
  cd ~/LinuxKernel/
  qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img
    //   -initrd file      Use file as initial ram disk.  
二、重新配置编译Linux使之携带调试信息
       在原来配置的基础上,make menuconfig选中如下选项重新配置Linux,使之携带调试信息
   kernel hacking—>[*] compile the kernel with debug info
     make重新编译(时间较长)
 
 三、使用gdb跟踪调试内核
  1、qemu -kernel linux-3.18.6/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、另开一个shell窗口
   gdb
  (gdb)file linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加载符号表
  (gdb)target remote:1234 # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行
  (gdb)break start_kernel # 断点的设置可以在target remote之前,也可以在之后
四、过程图示:
  1、可以看到QEMU 已经运行而且被“冻结”。(有几个文件没有,不影响后续操作)
        [img]http://img.blog.csdn.net/20160403175709815?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
   2、另外打开一个窗口,进入linuxkernel目录,输入gdb 回车
     [img]http://img.blog.csdn.net/20160403175908191?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
   3、输入:(gdb)file linux-3.18.6/vmlinux
            (gdb)target remote:1234
        (gdb)break start_kernel
        [img]http://img.blog.csdn.net/20160403175924957?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
   4、输入c 回车,可以看到内核继续启动,最后停在了start_kernel处:
             [img]http://img.blog.csdn.net/20160403175941566?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
更多gdb指令:
显示和查找程序源代码
(1)list :显示10行代码,但是我为什么没有显示成功呢?
(2)list 5,10:显示源文件第五行到第十行的代码
(3)list t4.c:5,10:显示源文件中第五行到第十行的代码,在跳是含有多个源文件的次序时使用;
(4)list get_sum:显示get_sum函数周围的代码//什么叫周围的代码呢?
(5)list t4.c :get_sum:显示源文件t4.c中第五行到第十行的代码,在跳是含有多个源文件的次序时使用;
(6)如果在调试中运行linux命令,则可以在gdb的提示符下输入shell命令. (gdb)shell ls
(7)search forward用来从当前行向前查找第一个匹配的字符串;
           search get_sum   forward get_sum
(8)reverse_search 用来从当前行想前查找第一个匹配的字符串:  Example:  reverse_search main
设置和管理断点:
(1)以行号设置断点:(gdb)break 7
(2)以函数名设置断点:(gdb)break get_sum
(3)以条件表达式设置断点:方法一:break 行号或者函数名 if  条件.  Example:  (gdb)break 7 if i==99
                                      方法二:watch 条件表达式,下面是具体的举例:
                                      方法三:awatch;用来给表达式设置断点,在表达式的值发生改变或者表达式的值杯读取的时候,程序暂时停止;
  (4).查看当前设置的断点:info breakpoints
 (5)使用“disable  断点编号”命令可以是某个断点失效,程序运行到该段点时不会停下来而是继续运行。
 (6)使用“enable 断点编号”命令可以是某个断点恢复有效。
彻底的删除某个断点,可以使用clear或者delete命令。
(1)clear:删除程序中所有的断点;
(2)clear 行号:删除此行中的断点
(3)clear 函数名:删除该函数的断点
(4)delete 断点编号:删除指定编号的断点。如果一次要删除多个断点,各个断点编号以空格隔开。
控制程序的执行:
(1)continue命令:让程序继续运行,直到下一个断点或者运行完为止。格式:continue
(2)kill命令:用于结束当前程序的调试
(3)next和step命令
   区别:如果遇到函数,next会把函数调用当作一条语句来执行,再次输入next会执行函数调用后的语句;
   而step则会跟踪进入函数,一次一条的执行函数内的代码,直到函数内的代码执行完,在进行函数调用后的语句;
(4)nexti和stepi命令:用来单步执行一条机器指令,注意不是单步执行一条鱼据。单步执行一条语句使用next和step命令。通常一条语句有多条机器指令构成的。
   注意的是:gdb的一些命令可以简写,比如list可以用li来代替,continue命令可以用cont来代替。
  
  5、继续输入 list start_kernel 查看start_kernel函数为中心上下10行的代码
    然后接着输入list 查看后续的代码(每输入一次list,向后显示10行)
       [img]http://img.blog.csdn.net/20160403180012254?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
   我们继续输入list跟踪start_kernel以后的代码,看看后面的执行过程:
    [img]http://img.blog.csdn.net/20160403180136817?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
    [img]http://img.blog.csdn.net/20160403180153395?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
   [img]http://img.blog.csdn.net/20160403180207833?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
   [img]http://img.blog.csdn.net/20160403180221520?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
可以看到,在start_kernel之后是一大堆的初始化操作,初始化外设、时钟、寄存器等。后面还有很多操作,这里不作过多的截图展示,
  6、后面进入rest_init函数:
    [img]http://img.blog.csdn.net/20160403180251505?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
 四、总结:
  在start_kernel中调用了一系列的初始化函数,已完成内核本身的设置:设置与体系结构相关的环境、进程调度器初始化、控制台初始化、系统IRQ初始化、内存初始化等。在Start_kernel函数的最后调用了rest_init()函数,在rest_init中建立了init线程,并在最后调用cpu_idle()函数。
  可以这样理解:start_kernel最后clone出一个新的进程,也就是init进程,然后原来的进程就去执行cpu_idle()函数了,也就变成了idle进程,当发生一次进程调度后,init进程被调度运行。
  核心进程init()主要进行一些外设初始化的工作包括SMP(Symmetric Multi-Processing 对称多处理)的初始化,以及调用do_basic_setup()完成外设及其驱动程序的加载和初始化,当do_basic_setup()函数返回init() ,init() 又打开了、dev/console设备,重定向输出文件到控制台,最后通过kernel——execve加载执行init程序。
  追踪到init后可以修改文件系统,比如把显示的MENUOS修改为MYOS,修改quit指令,让其退出文件系统等:
       [img]http://img.blog.csdn.net/20160403180403755?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
     [img]http://img.blog.csdn.net/20160403180416365?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
     [img]http://img.blog.csdn.net/20160403180430021?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img
    //   -initrd file      Use file as initial ram disk.
  这里将-initrd 后面的参数rootfs.img加载到内存中运行,所以,这里的rootfs.img 可以随便改名字,因为内核代码中不会直接用这个名字而是通过initrd来传递的。再者rootfs.img是由tootfs文件夹打包得来的,而rootfs文件夹中只有一个init可执行文件,而init可执行文件来自于menu文件夹,menu文件夹中执行make指令会发现生成了一个test可执行文件,运行menu文件夹中的test和init后会发现效果是一模一样的,所以显然init是由test通过(cp test  init) 拷贝、重命名得来的,所以最终修改文件系统可以归结为修改menu文件夹中的main.c、test.c文件。
  在init/initramfs.c文件中:
        [img]http://img.blog.csdn.net/20160403180529334?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
......显示全文...
    点击查看全文


上一篇文章      下一篇文章      查看所有文章
2016-04-03 20:46:11  
系统运维 最新文章
linux新进程的创建
Muduo网络库源码分析(一)EventLoop事件循
Linux系统分区
haproxylvsnginx负载均衡的比较
PeopleSoft介绍
win7+iis7+asp+.net+php环境配置
执行系统命令并且将输出写到指定日志文件的
linux批量替换多个文件中的字符串
makefile中=、:=和+=的区别
Linux服务器不关机新增硬盘的方法
360图书馆 软件开发资料 文字转语音 购物精选 软件下载 美食菜谱 新闻资讯 电影视频 小游戏 Chinese Culture 股票 租车
生肖星座 三丰软件 视频 开发 短信 中国文化 网文精选 搜图网 美图 阅读网 多播 租车 短信 看图 日历 万年历 2018年7日历
2018-7-22 15:02:54
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  软件世界网 --