(原创)构建嵌入式小型Linux系统
构建嵌入式小型Linux系统
摘要:用buildroot构建x86的交叉编译工具链;裁减linux内核,尽可能做到最小;手工构建根文件系统;安装qemu虚拟机,仿真新配置的Linux系统;为新配置的Linux系统添加网络支持,在host主机上用bridge-utils构建网桥,通过虚拟网卡tun/tap以NAT的方式使虚拟机能够上网。
一、安装qemu
QEMU是一款开源交叉平台仿真器。可以仿真许多硬件体系(x86,x86-64,PowerPC等)。
可以到http://wiki.qemu.org/Download上去下载qemu和加速器kqemu的源码进行安装,本文中选此时最新版qemu-0.12.3.tar.gz和kqemu-1.3.0pre11.tar.gz。
首先安装qemu
解压
$ tar zxf qemu-0.12.3.tar.gz
$ cd qemu-0.12.3
接下来configure,需要切换到root权限
$ /.configure –disable-curl
在我的安装的Centos4.8上,如若不禁掉此项,编译时会发生错误,缺少相关的库。
可以用/.configure –help来查看编译选项,并配置编译选项。
$ make
接下来,安装
# make install
在http://wiki.qemu.org/Download的上下载arm-test-0.2.tar.gz(ARM Linux 2.6 test kernel and initrd disk image (thanx to Paul Brook))和linux-0.2.img.bz2(Small Linux disk image containing a 2.6.20 Linux kernel, X11 and various utilities to test QEMU)用于测试,他们分别基于arm平台和x86平台的内核。
Use the executable ‘qemu-system-arm’ to simulate a ARM machine
# qemu-system-arm --kernel zImage.integrator -initrd arm_root.img
-kernel bzImage 选项use 'bzImage' as kernel image
-initrd file 选项 use 'file' as initial ram disk
登录后
qemu [options] [disk_image]
解压linux内核并用qemu启动
$ bunzip2 linux-0.2.img.bz2
$ qemu linux-0.2.img
显示结果
ctrl-alt-f 全屏
ctrl-alt 主机/虚拟机鼠标切换
Ctrl-Alt-n Switch to virtual console ’n’. Standard console mappings are:
1 Target system display
2 Monitor
3 Serial port
/*
同样的方法安装qemu的加速器kqemu。
用modprobe命令载入kqemu模块。modprobe可载入指定的个别模块,或是载入一组相依的模块。modprobe会根据depmod所产生的相依关系,决定要载入哪些模块。若在载入过程中发生错误,在modprobe会卸载整组的模块。
$ sudo /sbin/modprobe kqemu
使普通用户也能访问
$ sudo chmod 666 /dev/kqemu
*/
Qemu的kernel-kqemu并不能使用,我在qemu中也没有找到有关kqemu的选项,以为在./configure中出现了错误,但用./configure –help查看也没有看到有关使能kqemu的选项,不过在网上找到了一些言论说qemu0.12后不再用kqemu了。
“kqemu support has been removed for 0.12. I will make sure to make this very clear in the release notes.”
“Correct.kqemu has been unmaintained for the past 3-4 years. It's causing difficult to resolve functional regressions in qemu. We put out a call for someone to step up as maintainer and no one has. We deprecated it over the course of the 0.11 series (disabling it by default). After fair warning, we removed it as part of the 0.12 development cycle.Unfortunately, it requires a lot of work and no one has expressed any interest in maintaining it.”
“There hasn't been announcement on the website because we haven't released 0.12. It's been announced and discussed repeatedly on the mailing list.”
“But http://www.qemu.org is out-of-date.http://www.qemu.org/qemu-doc.html is from March, 8 2009.The qemu-doc.html of QEMU 0.12.0 rc1 is not correct.”
但是kqemu的文档一直没有更新。
二、用buildroot构建工具链
2.1 关于toolchain的一些概念
http://free-electrons.com/doc/embedded_lfs.pdf
Build a tiny embedded system entirely from scratch, in 40 minutes
Ø Linux kernel configuring and compiling
Ø Root filesystem creation
Ø Busybox compiling and installation
Ø Device file creation
Ø System initialization scripts: virtual filesystems, networking
Ø Setup of a simple HTTP interface to the system
Show you how simple this can be!
In software, a toolchain is the set of programming tools that are used to create a product (typically another computer program or system of programs). The tools may be used in a chain, so that the output of each tool becomes the input for the next, but the term is used widely to refer to any set of linked development tools.
--WikipediaàToolchain
一个简单的软件开发工具链主要包括
Ø Text editor:编辑源代码
Ø Compiler&Assembler:编译器源程序编译成汇编文件,汇编器把汇编文件编成目标文件。
Ø Linker:把目标文件链接成可执行的二进制文件(也可以是库文件,提供到操作系统的接口)。
Ø Debuger:调试器。
工具链可以分为以下几种
其中build,host和target的含义
Ø The build machine, where the toolchain is built.
Ø The host machine, where the toolchain will be executed.
Ø The target machine, where the binaries created by the toolchain will be executed.
在嵌入式系统中主要用到的是Cross-compiling toolchain,也就是toolchain的构建和执行在同一个平台上,而生成的二进制文件在另一个平台上执行。
构建一个Cross-compiling toolchain主要需要
编译一个Cross-Compiling toolchain的基本步骤
Ø Extract and install kernel headers
Ø Extract, configure, compile and install binutils
Ø Extract, configure and compile a first version gcc that generates binaries for the target. It will be used to cross compile the C library.
Ø Extract, configure and compile the C library using the previously generated compiler.
Ø Re configure and compile the final gcc cross compiler.
手动编译一个Cross-Compiling Toolchain是一项非常困难和痛苦的工作,可能要用几天甚至几周的时间。
可以用pre-compiled的toolchain,也可以用自动构建Cross-Compiling Toolchain的工具。
Crosstool,crosstool-ng,buildroot等,其中buildroot支持编译root filesystem,本文中选择使用buildroot工具。
2.2 关于Buildroot
About Buildboot
Buildroot是一系列的Makefile文件和patch文件,可以为指定的目标平台轻松地产生cross-compilation toolchain,root filesystem,和Linux kernel image。Buildroot可以只用作上述三个作用的某一单项或者某一组合项。
它主要应用于嵌入式系统目标平台一般不是PC上的x86而是Power PC,MIPS,ARM等
编译工具链是可以为目标平台编译代码提供一套工具,通常包括编译器(此处用gcc),binary utils(像汇编器和链接器,此处用binutils),和C标准库(比如GNU Libc,uClibc或者dietlibc)。在开发工作平台上安装的系统已经有一个编译工具链可以用来编译在工作平台上跑的程序。在大多的Linux系统下,编译工具链用GNU libc(glibc)作为标准C库。这个工具链叫做“host compilation toolchain”。它所运行的机器也就是你所使用的机器,被称为“host system”。
通常host system上的编译工具链在host system上的处理器运行并为之产生代码。而嵌入式系统通常包含一个不同的处理器,所以就需要一个cross-compilation toolchain,一个在host system上运行但为target system(and target processor)产生代码的编译工具链。例如x86和arm。
即使嵌入式系统是基于x86平台式,也常常选择Buildroot,这是因为:
Ø The compilation toolchain on your host certainly uses the GNU Libc which is a complete but huge C standard library. Instead of using GNU Libc on your target system, you can use uClibc which is a tiny C standard library. If you want to use this C library, then you need a compilation toolchain to generate binaries linked with it. Buildroot can do that for you.
Ø Buildroot automates the building of a root filesystem with all needed tools like busybox. That makes it much easier than doing it by hand.
也可以手动编译gcc, binutils, uClibc和其它的工具,但是它是非常time-consuming 和uninteresting的。Buildroot用Makefile和每一个gcc和binutils版本的patches自动完成这个工作,使它们可以在大部分的体系中工作。
而且,Buildroot可以kernel、cross-toolchain,和embedded root filesystem的构建重复进行。这当另有人接管项目时,或者当需要为项目升级或打补丁时就很有用。
2.3 使用Buildroot构建cross compile toolchain
参考文档http://buildroot.uclibc.org/buildroot.html
Obtain Buildroot
注:Make版本,buildroot的编译过程需要make不低于3.81,如若不符,下载安装make3.81吧ftp://ftp.gnu.org/pub/gnu/make/make-3.81.tar.gz
最新的版本总可以通过这个链接下载,应为buildroot的最新版本总是以
buildroot-snapshot.tar.bz2的名字做一份备份
http://buildroot.net/downloads/snapshots/buildroot-snapshot.tar.bz2
获得之前的版本,可以在下面的目录中需找
http://buildroot.net/downloads/snapshots/
但发现http://buildroot.uclibc.org/downloads/snapshots/中版本好像比buildroot.net中提供的还要全。
$ wget http://buildroot.net/downloads/snapshots/buildroot-snapshot.tar.bz2
也可以用git获得buildroot源码
$ git clone git://git.buildroot.net/buildroot
Using Buidroot
$ tar jxf buildroot-snapshot.tar.bz2
$ cd buildroot/
注意:可以用普通用户完成任何构建任务。没必要用root用户配置和使用Buidroot。
第一步是运行配置助手:
$ make menuconfig
这是基于curse方式的配置器。
试探性选择的一些选项:
Target Architecture: i386
Target Architecture Variant: i686
/*
Target ABI: EABI
关于ABI(application binary interface ,应用程序二进制接口)
application binary interface (ABI) 描述比应用程序和操作系统之间,应用程序和它的库之间,或者应用程序的不同组件之间的接口更低一层的接口。ABI与API(application programming interface)类似;只不过后者定义了一个代码接口。简而言之,ABI的作用是使二进制程序兼容,而API使代码间兼容。(ABIs enable binary compatibility, whereas APIs enable source code compatibility.)
*/
Target options随意设了一下
Buid Options选择默认
可以选择在编译过程中,Down dir,Mirror and Down location等选项。
Toolchain中几个重要选项
*** Kernel Header Options ***
Kernel Headers (Linux 2.6.33.x kernel headers) --->
*** uClibc Options ***
uClibc C library Version (uClibc 0.9.31.x) --->
*** Binutils Options ***
Binutils Version (binutils 2.20.1) --->
*** GCC Options ***
GCC compiler Version (gcc 4.3.4) --->
后记,如果使用busybox的defconfig配单编译,加上IPv6和RPC的支持吧,toolchain是在host主机上的,即使弄得大一点也没关系吧。
Package Selection for the target ---> 把默认的busybox勾掉(什么都不要选)
Target filesystem options ---> 把默认的ext2选项勾掉(什么都不要选)
Bootloaders ---> 什么都不选
Kernel ---> Kernel type (none)
目的是,只构建toolchain,其它的手动构建。
现在就可以运行make了
这个命令会自动执行一下几步
Ø Download source files (as required)
Ø Configure cross-compile toolchain
Ø Build/install cross-compile toolchain
Ø Build/install selected target packages
Ø Build a kernel image
Ø Create a root filesystem in selected formats
由于make中的第一步就是Download source files,我害怕会花费太长的时间,就想采取offline build的方式。
关于offline builds在Buildroot的网络文档中是这样介绍的:
Offline builds
If you intend to do an offline build and just want to download all sources that you previously selected in the configurator (menuconfig or xconfig), then issue:
$ make source
You can now disconnect or copy the content of your dl directory to the build-host.
我理解的是可以先把相关的源文件包binutils-2.20.1.tar.bz2、gcc-4.3.4.tar.bz2、
uClibc-0.9.31.tar.bz2、linux-2.6.33.2.tar.bz2分别下载到本地,拷贝到/buildroot的dl目录下。然后执行make source,便相当于执行了make命令,只不过不会再从远程机器上下载代码。但实际上make source命令还是对上述源码进行了下载(读Makefile不懂)。好在清晨的网速比较快(大概在350k以上)。而且我用的是最新的buildroot版本,不存在下载链接无效的问题。这两步比较顺利。
后记:源文件包的名字必须与buildroot中设置的版本完全一致,名字也相同,buildroot才不会再重新下载。
$ make source
$ make
在下载过程中下载了gmp-4.2.4.tar.bz2和mpfr-2.4.1.tar.bz2这两个文件,在安装gcc的过程中要用到,其中MPFR是高精度的浮点运算库,GMP是高精度数学库,MPFR需要它的支持。
make source后在dl中多了以下文件。
[lunix@localhost buildroot]$ cd dl;ls
binutils-2.20.1.tar.bz2 linux-2.6.33.2.tar.bz2 uClibc-0.9.31.tar.bz2
gcc-4.3.4.tar.bz2 mpfr-2.4.1.patch uClibc-0.9.31.tar.xz.tar
gmp-4.2.4.tar.bz2 mpfr-2.4.1.tar.bz2
buildroot的输出存放到一个文件夹下output,这个文件夹包括以下子文件夹:
Ø images/ where all the images (kernel image, bootloader and root filesystem images) are stored.
Ø build/ where all the components except for the cross-compilation toolchain are built (this includes tools needed to run Buildroot on the host and packages compiled for the target). The build/directory contains one subdirectory for each of these components.
Ø staging/ which contains a hierarchy similar to a root filesystem hierarchy. This directory contains the installation of the cross-compilation toolchain and all the userspace packages selected for the target. However, this directory is not intended to be the root filesystem for the target: it contains a lot of development files, unstripped binaries and libraries that make it far too big for an embedded system. These development files are used to compile libraries and applications for the target that depend on other libraries.
Ø target/ which contains almost the root filesystem for the target: everything needed is present except the device files in /dev/ (Buildroot can't create them because Buildroot doesn't run as root and does not want to run as root). Therefore, this directory should not be used on your target. Instead, you should use one of the images built in the images/ directory. If you need an extracted image of the root filesystem for booting over NFS, then use the tarball image generated in images/ and extract it as root.
Ø Compared to staging/, target/ contains only the files and libraries needed to run the selected target applications: the development files (headers, etc.) are not present.
Ø host/ contains the installation of tools compiled for the host that are needed for the proper execution of Buildroot except for the cross-compilation toolchain which is installed under staging/.
Ø toolchain/ contains the build directories for the various components of the cross-compilation toolchain.
本文中的配置生成的文件主要在staging和toolchain文件夹下,其它文件夹大多是空的。
Toolchain在/buildroot/output/staging/usr下。Export出来
$ export PATH=$PATH:/home/lunix/buildroot/buildroot/output/staging/usr/bin/
测试一下
[lunix@localhost bin]$ i686-linux-gcc –v
三、编译Linux小型内核
切换到linux的源码树下
$ cd /home/lunix/buildroot/buildroot/output/toolchain/linux-2.6.33.2/
制定最小内核
$ make allnoconfig
执行
$ make menuconfig
可发现所有可选的选项几乎都没有选
编译最小内核
$ make ARCH=i386 CROSS_COMPILE=i686-linux-
生成的内核bzImage在/buildroot/output/toolchain/linux-2.6.33.2/arch/x86/boot/下
查看大小
$ ll arch/x86/boot/bzImage
-rw-r--r-- 1 root root 712448 Apr 25 21:35 arch/x86/boot/bzImage
配置一个可以启动的内核
$ make mrproper
$ make allnoconfig
$ make menuconfig
怎样编译linux最小内核
模块一般用来支持那些不经常使用的功能。它们会根据你的使用与否决定模块被装入和被卸载,这样会使内核使用内存的量最小,减小系统的负荷。 当然,那些像硬盘访问这样时时刻刻都需要的功能,则必须作在内核里。按照这个原则,kernel 中有以下选项是必不可少的。
第一个是root所在的硬盘配置。本文中选IDE接口硬盘。ATA和ATAPI是广为使用的IDE和EIDE设备的相关标准。
在Device Driver中
选择了默认,在各个条目的Help菜单下,都有着一句If unsure, say N(Y),我相信了它。
第二个是选择使用哪一个文件系统。Linux的默认文件系统是是 ext2 ,那么就一定要把它标记下来。
在FILE system中
第三个是选择Linux所支持的可执行文件格式。这里有两种格式可供选择:
Ø elf:这是当前Linux普遍支持的可执行文件格式,必须编译到内核中。
Ø a.out:这是旧版的Linux的可执行文件各函数库的格式,如果你确认肯定用不到这种格式的可执行文件,那么就可以不把它编译到内核当中。
在Executable file formats/Emulations中
Exit,保存
# make ARCH=i386 CROSS_COMPILE=i686-linux-uclibc-
查看尺寸
# ls -l arch/x86/boot/bzImage
-rw-r--r-- 1 root root 789584 Apr 25 22:16 arch/x86/boot/bzImage
比纯allnoconfig大了一些。
四、创建root file system
制作rootfs.img文件映像。
关于根文件系统体制,始终没找到一些令人满意的比较详尽透彻的资料,以下是一些理解。
Linux根文件系统是在存放在存储介质上的文件系统启动之前,放到内存启动的一个系统,它主要的操作包括初始化和加载存储设备驱动的操作,不然,存储介质上的文件系统怎样启动呢。它是编译到内核中的。它主要包括一些内核启动所需要的文件和可执行程序。但这些可执行的程序从哪里来呢,--busybox。
BusyBox (http://www.busybox.net)将数以百计的常用Unix/Linux命令集成到一个可执行文件中(名为busybox).它体积小巧, 功能却不失强大.
Ø Most Unix command line utilities within a single executable!It even includes a web server!
Ø Sizes less than < 500 KB (statically compiled with uClibc) or less than 1 MB (statically compiled with glibc).
Ø Easy to configure which features to include.
Ø The best choice for
n Initramfs / initrd with complex scripts
n Small and medium size embedded systems
创建rootfs文件
# dd if=/dev/zero of=rootfs.img bs=1024k count=1
dd 是 Linux/UNIX 下的一个非常有用的命令,作用是用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换。
if=file 输入文件名,缺省为标准输入。
of=file 输出文件名,缺省为标准输出。
bs=bytes 同时设置读写块的大小为bytes,可代替ibs和obs。
格式化为ext2文件系统
# /sbin/mkfs.ext2 -i 1024 -F rootfs.img
-i选项: bytes-per-inode
下载busybox-snapshot.tar.bz2 本文中busybox-20100425的
# wget http://busybox.net/downloads/busybox-snapshot.tar.bz2
解压,切换到busybox目录
# tar jxf busybox-snapshot.tar.bz2
# cd busybox
配置安装菜单
$ make defconfig : 针对大多数用户的默认配置
$ make allnoconfig : 全不选
$ make allyesconfig : 全选
# make defconfig
# make menuconfig
可能是刚配置的编译链的问题吧,与网络有关的一些选项会出现错误,再回到toolchain编译的阶段加入IPv6和RPC的支持,网络无错误了,但仍有一个与fdisk有关的错误,直接在linux system utilities中把fdisk选项屏掉了。
Buid OptionàCross Compiler prefix,(avoid lib link problem)
它的help
CONFIG_CROSS_COMPILER_PREFIX:
If you want to build BusyBox with a cross compiler, then you
will need to set this to the cross-compiler prefix, for example,
"i386-uclibc-".
Note that CROSS_COMPILE environment variable or
"make CROSS_COMPILE=xxx ..." will override this selection.
使用i686-linux-uclibc-
在Installation Options选项中选择Don’t Use /usr/src
编译
# make
安装
# make install
默认地, 运行 make install之后, BusyBox将被安装到./_install目录.
查看大小
$ du -h _install/
1.8M _install/bin
368K _install/sbin
2.1M _install/
挂载文件系统
$ mkdir rootfs
# mount -o loop rootfs.img rootfs
Loop设备(Loop Device)是一个设备驱动,它允许一个镜像文件(image file)映射为类似普通的块设备。
Copying the busybox file structure into the mounted image
# rsync -a busybox/_install/ rootfs
# chown –R root:root rootfs
rsync文件系统刷新同步,它的关键特性是一个非常快的算法,它只通过数据链路发送文件差异,因此把机器之间传输的数据总量降低到最低限度。
# cd rootfs
# mkdir dev
到系统 /dev 把所有的device打一个包,拷贝到 dev下面(最省事的做法);或者使用mknod来自己建所需要的device,我自己用的如下
# cd dev
# mknod tty0 c 4 0
# mknod tty1 c 4 1
# mknod tty2 c 4 2
# mknod tty3 c 4 3
# mknod tty4 c 4 4
# mknod console c 5 1
# mknod null c 1 3
mknod 用指定名称产生一个FIFO(命名管道),字符专用或块专用文件。
创建/etc/inittab文件
# mkdir etc
# cd etc
# vi inittab
Inittab 文件内容的一个例子
# This is run first script
::sysinit:/etc/init.d/rcS
# Start an "askfirst" shell on the console
::askfirst:-/bin/sh
# Stuff to do when restarting the init process
::restart:/sbin/init
# Stuff to do before rebooting
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
编写rcS文件
# mkdir init.d
# vi rcS
RcS文件的内容
#!/bin/sh
mount –t proc none /proc
mount –t sysfs none /sys
/bin/sh
改变rcS的执行权限
# chmod a+x rcS
五、用qemu仿真制作的Linux内核
启动qemu虚拟机
# qemu ¥
-m 32 ¥ Amount of memory (MB) in the emulated target
-hda rootfs.img ¥ Contents of the emulated hard disk
-kernel linux-2.6.33.2/arch/i386/boot/bzImage ¥ Kernel image
–append "root=/dev/hda clock=pit" ¥ Kernel command line
‘-m megs’ Set virtual RAM size to megs megabytes. Default is 128 MiB. Optionally, a suffix of “M” or “G” can be used to signify a value in megabytes or gigabytes respectively.
‘-hda file’
‘-hdb file’
‘-hdc file’
‘-hdd file’
Use file as hard disk 0, 1, 2 or 3 image
‘-append cmdline’
Use cmdline as kernel command line
六、加入网络支持
重新配置linux内核,加上网络支持
在Bus option选项中
Networking support à Networking options à
Device DriversàNetwork Device SupportàEthernet(10 or 100Mbit)
后记,还需加入个芯片组支持
编译busybox时加入网络支持。
host上brctl创建桥接网路,并设置NAT
先安装bridge-utils
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/bridge-utils.git
brctl是一个网桥管理工具,用于在linux内核中建立,保存和检查网桥。网桥是一种把不同网络连接到一起的器件,使这些网段可以看做是,同一个网络的不同部分。
#./qemu-create-br0
#./setup_nat.sh
#cp qemu-ifup /etc
为了系统和网络能够启动,在rcS文件中加一些代码
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
ifconfig eth0 192.168.135.253 up
route add default gw 192.168.135.251
mount -o remount -o rw / /
/bin/sh
关于
ifconfig eth0 192.168.135.253 up
Bringing up the network interface
route add default gw 192.168.135.251
Using the GNU/Linux host as a gateway
关于以下这句代码
mount -o remount -o rw / /
加载/dev/root以可读写的方式到/下。
两点注意
Ø Do not forget #!/bin/sh at the beginning of shell scripts!Without the leading #! characters, the Linux kernel has no way to know it is a shell script and will try to execute it as a binary file!
Ø In our example, do not forget to start a shell at the end of the script. Otherwise, execution will just stop without letting you type new commands!
在/et c/目录下新建resolv.conf文件,配置域名服务器
nameserver 192.168.100.8
执行sync
重启虚拟机
qemu -m 32 ¥
-hda /home/lunix/rootfs.img ¥
-net nic,model=ne2k_pci -net tap ¥
-kernel linux-2.6.33.2/arch/i386/boot/bzImage ¥
-append "root=/dev/hda console=tty0"
现在虚拟机中就可以新建文件和访问网络了。
执行
ping www.google.com –c 3
-c 3: useful when [Ctrl][C] doesn't work(missing tty settings)
网络怎样建立起来的呢
qemu-create-br0中的代码
#!/bin/sh
if ! /sbin/ifconfig br0
then
/usr/sbin/brctl addbr br0
/usr/sbin/brctl addif br0 eth0
/sbin/ifconfig br0 up
addr=`/sbin/ip addr | grep eth0 | grep inet | sed -e 's/eth0/dev br0/' -e s/inet//`
/sbin/ip addr add $addr
fi
/usr/sbin/brctl stp br0 off
/sbin/ip route | grep eth0 | while read route
do
newroute=`echo $route | sed s/eth0/br0/ `
/sbin/ip route del $route
/sbin/ip route add $newroute
Done
Brctl用到的命令
Addbr <bridge> add brigdge
Addif <bridge> add interface to bridge
Stp <bridge>{on|off} turn stp on/off
这段脚步的作用,创建一个网桥br0,把eth0连接到br0的一个接口上,启动br0,并为它添加路由。
qemu-ifup文件的内容
#!/bin/sh
echo "Executing /etc/qemu-ifup"
echo "Bringing up $1 for bridged mode..."
/sbin/ifconfig $1 0.0.0.0 promisc up
echo "Adding $1 to br0..."
/usr/sbin/brctl addif br0 $1
echo "checking tap0 (ifconfig -a)"
/sbin/ifconfig –a
/etc/qemu-ifup是qemu的默认的脚本名称,也可以在启动时选择另外的脚本。
用ifconfig eth0 promisc将eth0设置成混杂模式.
混杂模式就是接收所有经过网卡的数据包,包括不是发给本机的包,即不验证MAC地址。
默认情况下网卡只把发给本机的包(包括广播包)传递给上层程序,其它的包一律丢弃。简单的讲,混杂模式就是指网卡能接受所有通过它的数据流,不管是什么格式,什么地址的。具体的地址转发则是在接受到数据后由MAC层来进行。
启动虚拟机时,自动加载网卡接口 tap0并为其分配一个IP(在/etc/qemu-ifup中设置),虚拟机的 eth0启动后相当于和 tap0接在同一个交换机上,两者只要IP设在同一网段即可相互访问。
$1 是qemu传递过来的网卡名称,即tap0。
关于 –net tap选项
‘-net tap[,vlan=n][,name=name][,fd=h][,ifname=name][,script=file][,downscript=dfile]’
Connect the host TAP network interface name to VLAN n, use the network script file to configure it and the network script dfile to deconfigure it. If name is not provided, the OS automatically provides one. ‘fd’=h can be used to specify the handle of an already opened host TAP interface. The default network configure script is ‘/etc/qemu-ifup’ and the default network deconfigure script is ‘/etc/qemu-ifdown’. Use ‘script=no’ or ‘downscript=no’ to disable script execution.
关于tun/tap的一些概念
In computer networking, TUN and TAP are virtual network kernel drivers. They implement network devices that are supported entirely in software, which is different from ordinary network devices that are backed up by hardwarenetwork adapters.
TAP (as in network tap) simulates an Ethernet device and it operates with layer 2 packets such as Ethernet frames. TUN(as in network TUNnel) simulates a network layer device and it operates with layer 3 packets such as IP packets. TAP is used to create a network bridge, while TUN is used with routing.
“TUN/TAP都是虚拟网络的内核驱动。他们完全以软件的方式实现了网络设备。TAP实现了以太网设备,它以软件的方式模拟了以太网的帧。TUN模拟了IP包,也就是说TAP工作在第二层,TUN工作在第三层。我们在/etc/qeum-ifup中创建了br0,tap0等网络设备,利用内核模块加载了tun设备,然后使真正的网络接口设备eth0和软件模拟的网络接口设备tap0都工作在混杂模式,并且eth0和tap0都连接在网桥br0上,这当然也是通过软件模拟实现的。”
setup_nat.sh脚步的内容
#!/bin/sh
sudo echo "1" > /proc/sys/net/ipv4/ip_forward
sudo /sbin/iptables -t nat -A POSTROUTING -o br0 -j MASQUERADE
sudo echo 1024 > /proc/sys/dev/rtc/max-user-freq
它的作用是利用iptables命令实现NAT转发功能,使虚拟机能够上网。
关于iptables的一些选项
-t, --table table
This option specifies the packet matching table which the command should operate on.
nat:
This table is consulted when a packet that creates a new connection is encountered. It consists of three built-ins: PREROUTING (for altering packets as soon as they come in),
OUTPUT (for altering locally-generated packets before routing), and POSTROUTING
(for altering packets as they are about to go out).
-A, --append
范例 iptables -A INPUT ...
说明 新增规则到某个规则炼中,该规则将会成为规则炼中的最后一条规则。
-j, --jump target
This specifies the target of the rule
-o, --out-interface
Name of an interface via which a packet is going to be sent.
虚拟机和主机网络的拓扑结构
此处用NAT方式实现虚拟机上网,网上有很多资料都是用openvpn工具来实现。
关于qemu/networking的脚本配置可参考http://en.wikibooks.org/wiki/QEMU/Networking
一些想法
本来觉得构建工具链是一个遥不可及的事情,但看了一篇手工配置microblaze编译工具链的文章,实验室论坛上也给出了一个构建arm工具链的脚本,看看工具链所需要的源代码的./configure文件中都有面向不同平台配置的选项,用手工的方法构建工具链应该是可行的,至于可不可用,可在开发板上试一下。
Embedded Linux Experts网站上的文章和实验应该学一遍。
可以用openvpn的方式再配置一下Qemu的网络,熟悉TUN/TAP,iptables,NAT,VPN的概念。