Linux内核学习 第三周 gdb跟踪Linux内核

一.搭建Linux内核编译、阅读环境。
    1.下载内核源码:
    wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.18.28.tar.xz
    xz -d linux-3.18.28.tar.xz
    tar-xvf linux-3.18.28.tar
    cd linux-3.18.28
    make i386_defconfig
    make  menuconfig  -> kernel hacking—>[*] compile the kernel with debug info  //这样会在内核调试阶段加入debug信息。
    make # 一般要编译很长时间,少则20分钟多则数小时
    有的系统可能出现: curses.h: No such file or directory  这个错误,这个是因为本机开启menuconfig界面时,需要creses字符库的支持,所以只需要在本机上安装库就可以了,我使用的是Ubuntu10.04,安装命令为: apt-get install libncurses5-dev

    2.制作文件系统
     # 制作根文件系统
    
mkdir rootfs
    
git clone https://github.com/mengning/menu.git  
    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

    3.运行内核
        qemu -kernel linux-3.18.28/arch/x86/boot/bzImage -initrd rootfs.img
    这时可以看到运行起来的menuos界面,并且通过 help命令可以查看支持的其他命令。



    4.使用vim搭建代码阅读环境,这个可以参考其他文档资料,我使用的是ctag+vim,参考来源为: http://blog.chinaunix.net/uid-22891435-id-380187.html

   二.使用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)冻结cpu
    # -s shorthand for -gdb tcp::1234 若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项
    2.gdb启动参数:
    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之前,也可以在之后
运行起来的效果图就如上面,区别在于,我们可以通过gdb添加断点来调试内核,跟踪内核的启动流程。
    a.我们添加第一个断点:
    在gdb中输入如下:break start_kernel        #break也可以使用单个字符 b 来代替
    然后 输入  continue        #continue 可以使用 单个字符 c 来代替
    进入如下打印片段,这是qemu已经进入了内核启动的开始阶段。

点击(此处)折叠或打开

  1. Breakpoint 1, start_kernel () at init/main.c:501
  2. 501    {
  3. (gdb)
     我们可以进入init/main.c 501行,可以看到很多初始化函数,下面只列举几个函数:
    

点击(此处)折叠或打开

  1. void set_task_stack_end_magic(struct task_struct *tsk)    //这个表示对任务列表进行初始化
  2.  {
  3.          unsigned long *stackend;
  4.  
  5.          stackend = end_of_stack(tsk);
  6.          *stackend = STACK_END_MAGIC; /* for overflow detection */
  7.  }
    在main.c中的调用为:

点击(此处)折叠或打开

  1. set_task_stack_end_magic(&init_task);   //对task进行初始化

点击(此处)折叠或打开

  1. void __init trap_init(void);    //完成硬件中断初始化
  2. mm_init();    //内存管理初始化
  3.  /*
     * Set up the scheduler prior starting any interrupts (such as the
     * timer interrupt). Full topology setup happens at smp_init()
     * time - but meanwhile we still have a functioning scheduler.
     */
      sched_init();    //如上所述,完成进程调度管理的初始化
  4. init_IRQ();    //初始化中断处理
  5. /*
    1. 从rest_init开始,Linux开始产生进程,因为init_task是静态制造出来的,pid=0,它试图将从最早的汇编代码一直到start_kernel的执行都纳入到init_task进程上下文中。在rest_init函数中,内核将通过下面的代码产生第一个真正的进程(pid=1):
    2. */
  6. rest_init();    
    rest_init();函数结束后,整个内核就开始了。


作者程大鹏,  转载请注明出处     http://blog.chinaunix.net/blog/post.html
Linux内核分析》MOOC课程 http://mooc.study.163.com/course/USTC-1000029000 ”



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值