virtualbox网络配置和调试linux内核

来源:互联网 发布:淘宝突然没有生意 编辑:程序博客网 时间:2024/06/16 03:10
VirtualBox的提供了四种网络接入模式,它们分别是: 
1、NAT 网络地址转换模式(NAT,Network Address Translation) 
2、Bridged Adapter 桥接模式 
3、Internal 内部网络模式 
4、Host-only Adapter 主机模式 

第一种 NAT模式 
解释: 
NAT模式是最简单的实现虚拟机上网的方式,你可以这样理解:Vhost访问网络的所有数据都是由主机提供的,vhost并不真实存在于网络中,主机与网络中的任何机器都不能查看和访问到Vhost的存在。 
虚拟机与主机关系: 
只能单向访问,虚拟机可以通过网络访问到主机,主机无法通过网络访问到虚拟机。 
虚拟机与网络中其他主机的关系: 
只能单向访问,虚拟机可以访问到网络中其他主机,其他主机不能通过网络访问到虚拟机。
虚拟机与虚拟机之间的关系: 
相互不能访问,虚拟机与虚拟机各自完全独立,相互间无法通过网络访问彼此。 
IP:10.0.2.15 
网关:10.0.2.2 
DNS:10.0.2.3 
一台虚拟机的多个网卡可以被设定使用 NAT, 第一个网卡连接了到专用网 10.0.2.0,第二个网卡连接到专用网络 10.0.3.0,等等。默认得到的客户端ip(IP Address)是10.0.2.15,网关(Gateway)是10.0.2.2,域名服务器(DNS)是10.0.2.3,可以手动参考这个进行修改。 
NAT方案优缺点: 
笔记本已插网线时: 虚拟机可以访问主机,虚拟机可以访问互联网,在做了端口映射后(最后有说明),主机可以访问虚拟机上的服务(如数据库)。 
笔记本没插网线时: 主机的“本地连接”有红叉的,虚拟机可以访问主机,虚拟机不可以访问互联网,在做了端口映射后,主机可以访问虚拟机上的服务(如数据库)。 

第二种 Bridged Adapter模式 
解释: 
网桥模式是我最喜欢的用的一种模式,同时,模拟度也是相当完美。你可以这样理解,它是通过主机网卡,架设了一条桥,直接连入到网络中了。因此,它使得虚拟机能被分配到一个网络中独立的IP,所有网络功能完全和在网络中的真实机器一样。 
虚拟机与主机关系: 
可以相互访问,因为虚拟机在真实网络段中有独立IP,主机与虚拟机处于同一网络段中,彼此可以通过各自IP相互访问。 
虚拟机于网络中其他主机关系: 
可以相互访问,同样因为虚拟机在真实网络段中有独立IP,虚拟机与所有网络其他主机处于同一网络段中,彼此可以通过各自IP相互访问。 
虚拟机于虚拟机关系: 
可以相互访问,原因同上。 
IP:一般是DHCP分配的,与主机的“本地连接”的IP 是同一网段的。虚拟机就能与主机互相通信。 
笔记本已插网线时:(若网络中有DHCP服务器)主机与虚拟机会通过DHCP分别得到一个IP,这两个IP在同一网段。 主机与虚拟机可以ping通,虚拟机可以上互联网。 
笔记本没插网线时:主机与虚拟机不能通信。主机的“本地连接”有红叉,就不能手工指定IP。虚拟机也不能通过DHCP得到IP地址,手工指定IP后,也无法与主机通信,因为主机无IP。 
这时主机的VirtualBox Host-Only Network 网卡是有ip的,192.168.56.1。虚拟机就算手工指定了IP 192.168.56.*,也ping不能主机。 

第三种 Internal模式 
解释: 
内网模式,顾名思义就是内部网络模式,虚拟机与外网完全断开,只实现虚拟机于虚拟机之间的内部网络模式。 
虚拟机与主机关系: 
不能相互访问,彼此不属于同一个网络,无法相互访问。 
虚拟机与网络中其他主机关系: 
不能相互访问,理由同上。 
虚拟机与虚拟机关系: 
可以相互访问,前提是在设置网络时,两台虚拟机设置同一网络名称。如上配置图中,名称为intnet。 
IP: VirtualBox的DHCP服务器会为它分配IP ,一般得到的是192.168.56.101,因为是从101起分的,也可手工指定192.168.56.*。 
笔记本已插网线时:虚拟机可以与主机的VirtualBox Host-Only Network 网卡通信 
这种方案不受主机本地连接(网卡)是否有红叉的影响。 

第四种 Host-only Adapter模式 
解释: 
主机模式,这是一种比较复杂的模式,需要有比较扎实的网络基础知识才能玩转。可以说前面几种模式所实现的功能,在这种模式下,通过虚拟机及网卡的设置都可以被实现。 
我们可以理解为Vbox在主机中模拟出一张专供虚拟机使用的网卡,所有虚拟机都是连接到该网卡上的,我们可以通过设置这张网卡来实现上网及其他很多功能,比如(网卡共享、网卡桥接等)。 
虚拟机与主机关系 
默认不能相互访问,双方不属于同一IP段,host-only网卡默认IP段为192.168.56.X 子网掩码为255.255.255.0,后面的虚拟机被分配到的也都是这个网段。通过网卡共享、网卡桥接等,可以实现虚拟机于主机相互访问。 
虚拟机与网络主机关系 
默认不能相互访问,原因同上,通过设置,可以实现相互访问。 
虚拟机与虚拟机关系 
默认可以相互访问,都是同处于一个网段。 
虚拟机访问主机 用的是主机的VirtualBox Host-Only Network网卡的IP:192.168.56.1 ,不管主机“本地连接”有无红叉,永远通。 
主机访问虚拟机,用是的虚拟机的网卡3的IP: 192.168.56.101 ,不管主机“本地连接”有无红叉,永远通。 
虚拟机访问互联网,用的是自己的网卡2, 这时主机要能通过“本地连接”有线上网,(无线网卡不行) 

通过对以上几种网络模式的了解,我们就可以灵活运用,模拟组建出我们所想要的任何一种网络环境了。 
比如我想模拟出来一个一台主机,监控一个局域网上网情况的网络环境。 
首先我开启了两台虚拟机vhost1与vhost2,当然如果硬件允许,我同样可以再增加vhost3、vhost4… 
所有的vhost我都设置成internat内网模式,网络名称为intnal,网关为192.168.56.100,意思就是通过 192.168.56.100网卡上网。其中有一台vhost1我设置为双网卡,一张为内网模式(192.168.56.100),一张为网桥模式(192.168.1.101)。两张网卡设置双网卡共享上网 
虚拟机之间为局域网,其中有一台虚拟机vhost1通过与外网相连,所有局域网中的虚拟机又通过vhost1来实现上外网。这样vhost1就可以监控整个虚拟机局域网上网情况了。 

NAT 设置端口映射 
http://huzhangsheng.blog.163.com/blog/static/34787784200802801435931/ 
你可以设置一个虚拟机的服务(比如 WEB 服务),通过使用命令行工具 VboxManage 代理。你需要知道虚拟机的服务使用哪个端口,然后决定在主机上使用哪个端口(通常但不总是想要使虚拟机和主机使用同一个端口)。在主机上提供一个服务需要使用一个端口,你能使用在主机上没有准备用来提供服务的任何端口。一个怎样设置新的 NAT 例子,在虚拟机上连接到一个 ssh 服务器,需要下面的三个命令: 
VBoxManage setextradata 'Linux Guest' 'VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/Protocol' TCP 
VBoxManage setextradata 'Linux Guest' 'VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/GuestPort' 22 
VBoxManage setextradata 'Linux Guest' 'VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/HostPort' 2222 
说明:VboxManage 是一个命令行程序,请查询你的 VirtualBox 安装目录,'Linux Guest' 是虚拟主机名。guestssh 是一个自定义的名称,你可以任意设置,通过上面的三个命令,把虚拟机的 22 端口 转发到主机的 2222 端口。 
又比如,我在虚拟机 debian 上安装了 apache2 服务器,使用 80 端口,映射到主机的 80 端口。使用下面的命令。 
'C:\Program Files\innotek VirtualBox\VBoxManage.exe' setextradata 'debian' 'VBoxInternal/Devices/pcnet/0/LUN#0/Config/huzhangsheng/Protocol' TCP 
'C:\Program Files\innotek VirtualBox\VBoxManage.exe' setextradata 'debian' 'VBoxInternal/Devices/pcnet/0/LUN#0/Config/huzhangsheng/GuestPort' 80 
'C:\Program Files\innotek VirtualBox\VBoxManage.exe' setextradata 'debian' 'VBoxInternal/Devices/pcnet/0/LUN#0/Config/huzhangsheng/HostPort' 80 

注意:要使设置生效,请关掉 VirtualBox 再运行虚拟机,我把 VirtualBox 安装在 winxp 上,在虚拟机中安装 debian 4.02r ,虚拟机名是 debian ,并安装了 apache2 php5 mysql-server ,在主机上用IE浏览 http://localhost,成功转发到虚拟机 debian 的 apache2 web 服务器上




windows host的vbox 串口可以选择namepipe,linux host同样可以选择这个配置。

 

在串口配置中选择host pipe,名称选择/tmp/vbox (这是local socket),选择为server(自动创建pipe文件)。

guest启动之后/tmp/vbox就建立起来了。

使用socat可以检查是否成功连接。

socat -d -d /home/fotisl/virtualbox/myvm/serial1 pty   (这里一定要是-d -d)

2009/01/01 00:00:00 socat[12345] N opening connection to AF=1 "/home/fotisl/virtualbox/myvm/serial1" 
2009/01/01 00:00:00 socat[12345] N successfully connected from local address AF=1 "/x04/b/xAB" 
2009/01/01 00:00:00 socat[12345] N successfully connected via /xD0/xA7/x10 
2009/01/01 00:00:00 socat[12345] N PTY is /dev/pts/4 
2009/01/01 00:00:00 socat[12345] N starting data transfer loop with FDs [3,3] and [4,4]

红字部分就是连接的目标

新开一个窗口打开gdb

gdb ~/vmlinux 
GNU gdb (GDB) 6.8.50.20090628-cvs-debian 
Copyright (C) 2009 Free Software Foundation, Inc. 
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i486-linux-gnu". For bug reporting instructions, please see: ... 
(gdb) set remotebaud 115200 
(gdb) target remote /dev/pts/4 
Remote debugging using /dev/pts/4

 

guest linux一定要编译了KGDB

同时设置

# echo ttyS0,115200 > /sys/module/kgdboc/parameters/kgdboc

用# echo g > /proc/sysrq-trigger  出发调试

如果是需要启动时调试,则增加boot参数。

kgdboc=ttyS0,115200 kgdbwait




14.1 利用bochs调试内核 
Bochs具有非常强大的操作系统内核调试功能。这也是本文选择Bochs作为首选实验环境的主要原因之一。有关Bochs调试功能的说明参见前面14.2节,这里基于Linux 0.11内核来说明Windows环境下Bochs系统调试操作的基本方法。

14.1.1 运行Bochs调试程序 
我们假设Bochs系统已被安装在目录“C:\Program Files\Bochs-2.1.1\”中,并且Linux 0.11系统的Bochs配置文件名称是bochsrc-hd.bxrc。现在在包含内核Image文件的目录下建立一个简单的批处理文件run.bat,其内容如下:

"C:\Program Files\Bochs-2.1.1\bochsdbg" -q -f bochsrc-hd.bxrc

其中bochsdbg是Bochs系统的调试执行程序。运行该批处理命令即可进入调试环境。此时Bochs的主显示窗口空白,而控制窗口将显示以下类似内容:

C:\Documents and Settings\john1\桌面\Linux-0.11>"C:\Program Files\Bochs-2.1.1\bo 
chsdbg" -q -f bochsrc-hd.bxrc 
======================================================================== 
                      Bochs x86 Emulator 2.1.1 
                          February 08, 2004 
======================================================================== 
00000000000i[     ] reading configuration from bochsrc-hd.bxrc 
00000000000i[     ] installing win32 module as the Bochs GUI 
00000000000i[     ] Warning: no rc file specified. 
00000000000i[     ] using log file bochsout.txt 
Next at t=0 
(0) context not implemented because BX_HAVE_HASH_MAP=0 
[0x000ffff0] f000:fff0 (unk. ctxt): jmp f000:e05b             ; ea5be000f0 
<bochs:1>

此时Bochs调试系统已经准备好开始运行,CPU执行指针已指向ROM BIOS中地址0x000fffff0处的指令处。其中'<bochs:1>'是命令输入提示符,其中的数字表示当前的命令序列号。在命令提示符'<bochs:1>'后面键入'help'命令,可以列出调试系统的基本命令。若要了解某个命令的具体使用方法,可以键入'help'命令并且后面跟随一个用单引号括住的具体命令,例如:“help 'vbreak'”,如下面所示。

<bochs:1> help 
help - show list of debugger commands 
help 'command'- show short command description 
-*- Debugger control -*- 
   help, q|quit|exit, set, instrument, show, trace-on, trace-off, 
   record, playback, load-symbols, slist 
-*- Execution control -*- 
   c|cont, s|step|stepi, p|n|next, modebp 
-*- Breakpoint management -*- 
   v|vbreak, lb|lbreak, pb|pbreak|b|break, sb, sba, blist, 
   bpe, bpd, d|del|delete 
-*- CPU and memory contents -*- 
   x, xp, u|disas|disassemble, r|reg|registers, setpmem, crc, info, dump_cpu, 
   set_cpu, ptime, print-stack, watch, unwatch, ?|calc 
<bochs:2> help 'vbreak' 
help vbreak 
vbreak seg:off - set a virtual address instruction breakpoint 
<bochs:3>

为了让Bochs直接模拟执行到Linux的引导启动程序开始处,我们可以先使用断点命令在0x7c00处设置一个断点,然后让系统连续运行到0x7c00处停下来。执行的命令序列如下:

<bochs:3> vbreak 0x0000:0x7c00 
<bochs:4> c 
(0) Breakpoint 1, 0x7c00 (0x0:0x7c00) 
Next at t=4409138 
(0) [0x00007c00] 0000:7c00 (unk. ctxt): mov ax, 0x7c0             ; b8c007 
<bochs:5>

此时,CPU执行到boot.s程序开始处的第1条指令处,Bochs主窗口将显示出“Boot From floppy...”等一些信息。现在,我们可以利用单步执行命令's'或'n'(不跟踪进入子程序)来跟踪调试程序了。在调试时可以使用Bochs的断点设置命令、反汇编命令、信息显示命令等来辅助我们的调试操作。下面是一些常用命令的示例:

<bochs:8> u /10                                    # 反汇编从当前地址开始的10条指令。 
00007c00: (                    ): mov ax, 0x7c0             ; b8c007 
00007c03: (                    ): mov ds, ax                ; 8ed8 
00007c05: (                    ): mov ax, 0x9000            ; b80090 
00007c08: (                    ): mov es, ax                ; 8ec0 
00007c0a: (                    ): mov cx, 0x100             ; b90001 
00007c0d: (                    ): sub si, si                ; 29f6 
00007c0f: (                    ): sub di, di                ; 29ff 
00007c11: (                    ): rep movs word ptr [di], word ptr [si] ; f3a5 
00007c13: (                    ): jmp 9000:0018             ; ea18000090 
00007c18: (                    ): mov ax, cs                ; 8cc8 
<bochs:9> info r                                  # 查看当前CPU寄存器的内容 
eax            0xaa55           43605 
ecx            0x110001         1114113 
edx            0x0              0 
ebx            0x0              0 
esp            0xfffe           0xfffe 
ebp            0x0              0x0 
esi            0x0              0 
edi            0xffe4           65508 
eip            0x7c00           0x7c00 
eflags         0x282            642 
cs             0x0              0 
ss             0x0              0 
ds             0x0              0 
es             0x0              0 
fs             0x0              0 
gs             0x0              0 
<bochs:10> print-stack                            # 显示当前堆栈的内容 
  0000fffe [0000fffe]  0000 
  00010000 [00010000]  0000 
  00010002 [00010002]  0000 
  00010004 [00010004]  0000 
  00010006 [00010006]  0000 
  00010008 [00010008]  0000 
  0001000a [0001000a]  0000 
... 
<bochs:11> dump_cpu                               # 显示CPU中的所有寄存器和状态值。 
eax:0xaa55 
ebx:0x0 
ecx:0x110001 
edx:0x0 
ebp:0x0 
esi:0x0 
edi:0xffe4 
esp:0xfffe 
eflags:0x282 
eip:0x7c00 
cs:s=0x0, dl=0xffff, dh=0x9b00, valid=1 
ss:s=0x0, dl=0xffff, dh=0x9300, valid=7 
ds:s=0x0, dl=0xffff, dh=0x9300, valid=1 
es:s=0x0, dl=0xffff, dh=0x9300, valid=1 
fs:s=0x0, dl=0xffff, dh=0x9300, valid=1 
gs:s=0x0, dl=0xffff, dh=0x9300, valid=1 
ldtr:s=0x0, dl=0x0, dh=0x0, valid=0 
tr:s=0x0, dl=0x0, dh=0x0, valid=0 
gdtr:base=0x0, limit=0x0 
idtr:base=0x0, limit=0x3ff 
dr0:0x0 
dr1:0x0 
dr2:0x0 
dr3:0x0 
dr6:0xffff0ff0 
dr7:0x400 
tr3:0x0 
tr4:0x0 
tr5:0x0 
tr6:0x0 
tr7:0x0 
cr0:0x60000010 
cr1:0x0 
cr2:0x0 
cr3:0x0 
cr4:0x0 
inhibit_mask:0 
done 
<bochs:12>

由于Linux 0.11内核的32位代码是从绝对物理地址0处开始存放的,因此若想直接执行到32位代码开始处,即head.s程序开始处,我们可以在线性地址0x0000处设置一个断点并运行命令'c'执行到那个位置处。 
另外,当直接在命令提示符下打回车键时会重复执行上一个命令;按向上方向键会显示上一命令。其他命令的使用方法请参考'help'命令。

14.1.2 定位内核中的变量或数据结构 
在编译内核时会产生一个system.map文件。该文件列出了内核Image (bootimage)文件中全局变量和各个模块中的局部变量的偏移地址位置。在内核编译完成后可以使用前面介绍的文件导出方法把system.map文件抽取到主机环境(windows)中。有关system.map文件的详细功能和作用请参见2.10.3节。system.map样例文件中的部分内容见如下所示。利用这个文件,我们可以在Bochs调试系统中快速地定位某个变量或跳转到指定的函数代码处。

... 
Global symbols:

 _dup: 0x16e2c 
 _nmi: 0x8e08 
 _bmap: 0xc364 
 _iput: 0xc3b4 
 _blk_dev_init: 0x10ed0 
 _open: 0x16dbc 
 _do_execve: 0xe3d4 
 _con_init: 0x15ccc 
 _put_super: 0xd394 
 _sys_setgid: 0x9b54 
 _sys_umask: 0x9f54 
 _con_write: 0x14f64 
 _show_task: 0x6a54 
 _buffer_init: 0xd1ec 
 _sys_settimeofday: 0x9f4c 
 _sys_getgroups: 0x9edc 
...

同样,由于Linux 0.11内核的32位代码是从绝对物理地址0处开始存放的,system.map中全局变量的偏移位置值就是CPU中线性地址位置,因此我们可以直接在感兴趣的变量或函数名位置处设置断点,并让程序连续执行到指定的位置处。例如若我们想调试函数buffer_init(),那么从system.map文件中可以知道它位于0xd1ec处。此时我们可以在该处设置一个线性地址断点,并执行命令'c'让CPU执行到这个指定的函数开始处,见如下所示。

<bochs:12> lb 0xd1ec                              # 设置线性地址断点。 
<bochs:13> c                                      # 连续执行。 
(0) Breakpoint 2, 0xd1ec in ?? () 
Next at t=16689666 
(0) [0x0000d1ec] 0008:0000d1ec (unk. ctxt): push ebx                  ; 53 
<bochs:14> n                                      # 执行下一指令。 
Next at t=16689667 
(0) [0x0000d1ed] 0008:0000d1ed (unk. ctxt): mov eax, dword ptr ss:[esp+0x8] ; 8b442408 
<bochs:15> n                                      # 执行下一指令。 
Next at t=16689668 
(0) [0x0000d1f1] 0008:0000d1f1 (unk. ctxt): mov edx, dword ptr [ds:0x19958] ; 8b1558990100 
<bochs:16>

程序调试是一种技能,需要多练习才能熟能生巧。上面介绍的一些基本命令需要组合在一起使用才能灵活地观察到内核代码执行的整体环境情况。


原创粉丝点击