Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2151607
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2013-07-30 11:40:46

一.qemu模拟x86
1.1 qemu的安装
        ubuntu 12.04下安装qemu很简单,
        sudo apt-get install qemu
1.2 linux内核的编译
    下载内核, 以linux-3.0.1为例
    sun@ubuntu:/work/x86/kernel$ tar xf ./linux-3.0.1.tar.bz2
    sun@ubuntu:/work/x86/kernel$ cd linux-3.0.1/
    sun@ubuntu:/work/x86/kernel/linux-3.0.1$ make menuconfig
    sun@ubuntu:/work/x86/kernel/linux-3.0.1$ make bzImage
    这样就会生成内核文件 arch/x86/boot/bzImage
1.3 busybox的编译
     下载busybox, 以busybox-1.21.1.tar.bz2为例
    sun@ubuntu:/work/x86/kernel$ tar xv busybox-1.21.1.tar.bz2
    sun@ubuntu:/work/x86/kernel$ cd busybox-1.21.1/
    sun@ubuntu:/work/x86/kernel/busybox-1.21.1$ make menuconfig
     Busybox Settings  ---> 
           Build Options  --->
               [*] Build BusyBox as a static binary (no shared libs)           //静态方式编译
     Networking Utilities  --->
          [ ] inetd                                                                                 //去掉inetd
   sun@ubuntu:/work/x86/kernel/busybox-1.21.1$ make install
       这会生成 _install目录
1.4 最小文件系统的建立
只用一个脚本creatfs.sh就可以生成cramfs文件系统
  1. #!/bin/sh
  2. KERNEL=$(pwd)
  3. BUSYBOX=$(find busybox* -maxdepth 0)
  4. LINUX=$(find linux* -maxdepth 0)

  5. #create filesystem
  6. cd $BUSYBOX
  7. mkdir -pv proc sys dev etc etc/init.d      //先创建系统目录
  8. cat << EOF > etc/init.d/rcS                //生成rcS文件
  9. #!/bin/sh
  10. mount -t proc none /proc
  11. mount -t sysfs none /sys
  12. /sbin/mdev -s
  13. EOF

  14. chmod 777 ./etc/init.d/rcS                //修改rcS权限
  15. cd -

  16. #create cpio img
  17. cd $BUSYBOX/_install
  18. find . | cpio -o --format=newc > $KERNEL/rootfs.img 
  19. cd -

  20. #create zip img
  21. cd $KERNEL
  22. gzip -c rootfs.img > rootfs.img.gz
1.5 启动qemu
  1. #!/bin/sh
  2. LINUX=$(find linux* -maxdepth 0)
  3. #启动qemu
  4. if [ $# = 0 ] ; then
  5.     qemu-system-i386 -kernel $LINUX/arch/i386/boot/bzImage -initrd rootfs.img.gz -append "root=/dev/ram rdinit=sbin/init noapic"
  6. fi

  7. if [ "$1" = "s" ] ; then
  8.     qemu-system-i386 -s -S -kernel $LINUX/arch/i386/boot/bzImage -initrd rootfs.img.gz -append "root=/dev/ram rdinit=sbin/init noapic"
  9. fi
如果没有参数直接运行qemu, 如果有参数s, 则进入调试模式
qemu参数: 
    -s  :  在1234接受gdb调试连接
    -S :   虚拟机启动后立即暂停,等侍gdb连接
最后所有文件如下:
sun@ubuntu:/work/x86/kernel$ tree -L 1
.
├── busybox-1.21.1        //busbyox及_install
├── creatfs.sh                 //文件系统生成脚本   
├── linux-3.0.1              //Linux源码,及 bzImage
└── start.sh                   //启动qemu

注意:
a. 将linux启动信息打印到串口

在qemu启动时加上: 
      qemu-system-i386 -kernel $LINUX/arch/i386/boot/bzImage -initrd rootfs.img.gz -append "root=/dev/ram rdinit=sbin/init noapic console=ttyS0" -serial file:/tmp/serial.out
就会在/tmp/serial.out中出现系统的信息
b.  将linux启动信息直接打印到控制台
加入 -nographic 和stdio,则会在当前运行的terminal中把linux启动信息打印出来
qemu-system-i386 -kernel $LINUX/arch/i386/boot/bzImage -initrd rootfs.img.gz -append "root=/dev/ram rdinit=sbin/init console=ttyS0" -nographic
c. qemu的快捷键
C-a h    print this help
C-a x    exit emulator
C-a s    save disk data back to file (if -snapshot)
C-a t    toggle console timestamps
C-a b    send break (magic sysrq)
C-a c    switch between console and monitor
C-a C-a  sends C-a

二.qemu模拟ARM
 2.1 qemu-system-arm的安装
如果只是apt-get install qemu,不会安装qemu-system-arm
sun@ubuntu:/work/qemu$ sudo apt-get install qemu qemu-system qemu-utils
sun@ubuntu:/work/qemu$ qemu-system-arm  --version
QEMU emulator version 1.0.50 (Debian 1.0.50-2012.03-0ubuntu2.1), Copyright (c) 2003-2008 Fabrice Bellard
注意: 编译工具链可以不用apt-get install 来安装,试过6410自带的交叉编译工具链是完全可用的。
2.2 编译u-boot, kernel, busybox
这儿的编译跟x86的不同之处是:
不论是编译u-boot 还是 linux-3.0.1 还是busybox都需要个改Makefile中的ARCH与CROSS_COMPILE两个变量c
  1. ARCH ?= arm
  2. CROSS_COMPILE ?= /opt/6410/4.3.2/bin/arm-none-linux-gnueabi-
编译u-boot时是用的make ca9x4_ct_vxp_config
编译Linux-3.0.1时是用的 arch/arm/configs/vexpress_defconfig
内核编译命令: make vexpress_defconfig && make -j16
a.copy zImage
在arch/arm/Makefile中
  1. 278 zImage Image xipImage bootpImage uImage: vmlinux
  2. 279 $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
  3. 280 echo "$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@"
  4. 281 cp $(boot)/$@ ../
其中$(boot)/$@是zImage的路径
../ 是linux-3.01源码的上一层

2.3 用ext3系统启动
编译完成busybox, make install 后,用mkfs.sh脚本生成文件系统,只是生成,不用打包成其它格式
  1. #!/bin/sh
  2. KERNEL=$(pwd)
  3. BUSYBOX=$(find busybox* -maxdepth 0)
  4. LINUX=$(find linux* -maxdepth 0)
  5. #create filesystem
  6. cd $BUSYBOX
  7. mkdir -pv proc sys dev etc etc/init.//先创建系统目录
  8. cat << EOF > etc/init.d/rcS //生成rcS文件
  9. #!/bin/sh
  10. mount -t proc none /proc
  11. mount -t sysfs none /sys
  12. /sbin/mdev -s
  13. EOF
  14. chmod 777 ./etc/init.d/rcS //修改rcS权限
  15. cd -
用ext3.sh脚本创建ext3文件系统
  1. #!/bin/sh
  2. #创建一个32M的空文件
  3. dd if=/dev/zero of=a9rootfs.ext3 bs=1M count=32 

  4. #格式化为EXT3
  5. sudo mkfs.ext3 a9rootfs.ext3 

  6. # 挂载到a9rootdir目录
  7. mkdir -pv /tmp/a9rootdir
  8. sudo mount -t ext3 a9rootfs.ext3 /tmp/a9rootdir/ -loop

  9. #拷贝文件到该目录,相对于放到a9rootfs.ext3里面
  10. sudo cp /work/qemu/rootfs/* /tmp/a9rootdir/ -Rf

  11. sudo umount /tmp/a9rootdir
2.3.1文件系统的目录结构
  1. cong@msi:/tmp/a9rootdir$ tree
  2. .
  3. ├── bin
  4. │   ├── busybox
  5. │   ├── init -> busybox
  6. │   ├── ls -> busybox
  7. │   ├── mount -> busybox
  8. │   └── sh -> busybox
  9. ├── dev
  10. │   ├── console
  11. │   ├── null
  12. │   └── tty1
  13. ├── etc
  14. │   ├── fstab
  15. │   ├── init.d
  16. │   │   └── rcS
  17. │   └── inittab
  18. ├── lib
  19. │   ├── ld-2.8.so                     -->解释器
  20. │   ├── ld-linux.so.3 -> ld-2.8.so
  21. │   ├── libc-2.8.so                   -->libc库运行时必需
  22. │   ├── libcrypt-2.8.so               -->libcrypt是busybox需要用的
  23. │   ├── libcrypt.so.1 -> libcrypt-2.8.so
  24. │   ├── libc.so.6 -> libc-2.8.so
  25. │   ├── libgcc_s.so -> libgcc_s.so.1
  26. │   ├── libgcc_s.so.1                 -->运行时必需
  27. │   ├── libm-2.8.so                   -->libm是busybox需要用的
  28. │   └── libm.so.6 -> libm-2.8.so
  29. ├── linuxrc -> ./bin/busybox
  30. ├── lost+found [error opening dir]
  31. ├── proc
  32. ├── sbin
  33. │   └── mdev -> ../bin/busybox
  34. └── sys
2.3.2启动的流程
kernel-->/bin/init -->/etc/inittab--> /etc/init.d/rcS --> mount 会用到/etc/fstab
  1. cong@msi:/tmp/a9rootdir$ cat etc/inittab
  2. ::sysinit:/etc/init.d/rcS
  3. ttyAMA0::askfirst:-/bin/sh
  4. #console::askfirst:-/bin/sh
  5. cong@msi:/tmp/a9rootdir$ cat etc/init.d/rcS
  6. #!/bin/sh
  7. mount -a
  8. /sbin/mdev -s
  9. cong@msi:/tmp/a9rootdir$ cat etc/fstab
  10. proc /proc proc defaults 0 0
  11. sysfs /sys sysfs defaults 0 0
2.3.3启动:
  1. qemu-system-arm -kernel zImage -M vexpress-a9 -append "root=/dev/mmcblk0 console=ttyAMA0 console=tty0" -sd a9rootfs.ext3 -serial stdio
2.4 用NFS启动
编译完成busybox, make install 后,用mkfs.sh脚本生成文件系统,只是生成,不用打包成其它格式
启动:
  1. qemu-system-arm -m 256 -kernel zImage -serial stdio -M vexpress-a9 -append root="/dev/nfs console=ttyAMA0 console=tty0 nfsroot=10.0.0.1:/work/qemu/rootfs rw ip=10.0.0.2:10.0.0.1:10.0.0.1:255.255.255.0 " -net nic,vlan=0 -net tap,vlan=0,ifname=tap0,script=qemu-ifup &
qemu-ifup脚本如下:
  1. #!/bin/sh
  2. echo "Executing /etc/qemu-ifup"
  3. sudo ifconfig $1 10.0.0.1
前提是主机上的nfs-server己配置好

三. qemu调试linux系统

3.1 启动调试模式下的qemu
   sun@ubuntu:/work/x86/kernel$ sh start.sh s
3.2 另起一个terminal
  1. sun@ubuntu:/work/x86/kernel/linux-3.0.1$ gdb vmlinux
  2. Reading symbols from /work/x86/kernel/linux-3.0.1/vmlinux...done.
  3. (gdb) target remote localhost:1234
  4. Remote debugging using localhost:1234
  5. 0x0000fff0 in ?? ()
  6. (gdb) b kernel_init
  7. Breakpoint 1 at 0xc15c7786: file init/main.c, line 781.
  8. (gdb) c
  9. Continuing.

  10. Breakpoint 1, kernel_init (unused=0x0) at init/main.c:781
  11. 781    {
  12. (gdb) l
  13. 776        panic("No init found. Try passing init= option to kernel. "
  14. 777         "See Linux Documentation/init.txt for guidance.");
  15. 778    }
  16. 779    
  17. 780    static int __init kernel_init(void * unused)
  18. 781    {
  19. 782        /*
  20. 783         * Wait until kthreadd is all set-up.
  21. 784         */
  22. 785        wait_for_completion(&kthreadd_done);
  23. (gdb)
3.3 每次都这么操作比较麻烦,可以建立一个gdbinit脚本
sun@ubuntu:/work/x86/kernel/linux-3.0.1$ vi .gdbinit
  1. target remote localhost:1234
  2. b kernel_init
  3. c
然后下次运行时就可以
sun@ubuntu:/work/x86/kernel/linux-3.0.1$ gdb vmlinux
注意,如果用gdbinit脚本时出现以下问题:
  1. warning: File "/work/x86/kernel/linux-3.0.1/.gdbinit" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load".
  2. To enable execution of this file add
  3.     add-auto-load-safe-path /work/x86/kernel/linux-3.0.1/.gdbinit
  4. line to your configuration file "/home/sun/.gdbinit".
  5. To completely disable this security protection add
  6.     set auto-load safe-path /
  7. line to your configuration file "/home/sun/.gdbinit".
  8. For more information about this security protection see the
  9. "Auto-loading safe path" section in the GDB manual. E.g., run from the shell:
  10.     info "(gdb)Auto-loading safe path"
sun@ubuntu:/work/x86/kernel/linux-3.0.1$ vi ~/.gdbinit
 set auto-load safe-path /
在~/.gdbini中加入上面这一行,取消掉

 [参]:
以QEMU模拟Linux,学习linux内核
http://www.cnblogs.com/senix/archive/2013/02/21/2921221.html
使用qemu调试linux内核
http://blog.csdn.net/aero_boy/article/details/6262609
使用qemu模拟Coretex-A9运行u-boot和Linux

阅读(11275) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~