《[计算机软件及应用]VirtualBox.doc》由会员分享,可在线阅读,更多相关《[计算机软件及应用]VirtualBox.doc(32页珍藏版)》请在三一办公上搜索。
1、VirtualBox + Ubuntu配置备忘录(一)基本配置开始接触Linux已经十多年了,最早是用请人在一台淘汰的奔II机器上用ipchains配一个代理服务器,供一屋子的人上网。后来又给实验室配过Web服务,很快被好事者黑掉作罢,只保留了一个不知名的BT客户端供自己娱乐用。再后来学嵌入式又配过一次,其他乱七八糟的折腾不一而足,但三天打鱼,两天晒网,每次都要现用现学,始终连门都没入。这回决定吸取教训,把配置过程记录下来,以强大的“外脑”补充日渐萎缩的“内脑”,也给跟自己同样的阿兹海默+帕金森患者作为参考。 Linux选择的是Ubuntu 10.10,在VirtualBox 4.1.10下运
2、行,宿主机操作系统是Win7 SP1。配置目的是让Ubuntu与宿主机方便互通,操作习惯接近,使用舒适。Linux的版本选择Ubuntu主要是因为它界面类似于windows,学习曲线比较平缓,这显然要被无数人鄙视了。不过在我看来,大脑的黄金阶段过了就不能逞强,学习成本和使用成本的总和是因人而异的,选择最适合自己的就好。闲话少叙,下面是最初步的配置过程。一、安装VirtualBox Guest Additions 在ubuntu的运行窗口上选择“设备”“安装增强功能”菜单,此时一张虚拟光盘就被挂载到了ubuntu系统里,一般情况下会在桌面上显示为一个光盘图标,名字就是光盘对应文件夹的目录,一般是
3、“VBOXADDITIONS+版本号”的一长串。 多数情况下,系统会提示自动安装,如果没有自动安装。需要在命令行中,输入如下命令: cd /media/VBOXADDITIONS_xxxxx_yyyy sudo ./VBoxLinuxAdditions.run xxxx和yyyy是一长串版本号,注意使用tab补齐命令的功能。命令开始执行,输入密码后,增强包会自动安装,然后重启。注意对于不同版本的VirtualBox,光盘的目录名也不同。此外每次升级ubuntu后增强功能都会失效,所以在升级后需要重新安装增强功能。二、配置显示分辨率 输入: sudo gedit /etc/X11/xorg.co
4、nf 在打开的文件夹中找到下面一段: Section Screen SubSection Display Depth 24 Modes 1280x800 1024x768 800x600 EndSubSection Device Device0 Identifier Screen0 Monitor Monitor0 EndSection 在“Modes”这一行中将你想要的分辨率加进去。重启后,通过“系统”菜单里面的“首选项显示器”像Windows系统一样设屏幕分辨率即可。三、配置网络 配置网络主要目的有两个,其一是能够使虚拟机上网,其二是在宿主机没有接入网络时能够让宿主机和虚拟机通信。 1.
5、网络接入模式选择 在VirtualBox的网络接入模式中,有Bridge Adapter(桥接)、NAT(网络地址转换)、Host-Only(主机)、Internal(内网)、Generic Driver这5种模式。 Bridge Adapter模式下,虚拟机的虚拟网卡VA接入了VirtualBox生成的一个虚拟交换机VS,而在宿主机看来VS是个程序。VirtualBox在与虚拟机绑定的宿主机网卡HA上多设置了一个ip地址供VS使用(HA和VS间可能还有其他层次),这个地址与VA上设置的ip地址相同。这样虚拟机在外界看来是一个独立的主机,对虚拟机的访问和对宿主机的访问使用了不同ip。发送给虚拟
6、机ip地址的数据包,由VirtualBox通过VS转发给VA,进而由虚拟机上的操作系统处理。在这种模式下,如果VA配置为自动获取网络地址,虚拟交换机会自动在HA上设置一个与宿主机同网段的ip,并将这个ip分配给VA,把宿主机网段的网关地址作为虚拟交换机的网关地址。同理,如果VA手工设置ip,需要将其设置为宿主机的同网段ip,并与宿主机有相同网关。 NAT模式下,VirtualBox同样为VA提供了虚拟交换机VS,但不为VS在宿主机网卡上单独设置ip,而是将虚拟机的数据表经过地址转换,通过宿主机的ip地址发送出去,这样虚拟机在外界是不可见的,也不能向外提供服务。此时虚拟机的网络地址只能由虚拟交换
7、机自动分配。 Host-Only模式下,VirtualBox在宿主机中生成了一块虚拟网卡VHA,为其分配了地址,并将VA和VHA都接入了VS。这样虚拟机和主机就可以实现通信。如果将VHA与宿主机其他网卡共享连接,也可以接入外网(虽然一般无此必要)。此时应当将VA的地址设置在VHA相同网段下,一般同时将网关设置为VHA的地址。 Internal模式下,一台宿主机上的所有虚拟机都接入VS,可以实现虚拟机间互相访问,但不能连接外网。 Generic Driver模式是用于建立分布式虚拟网络的,比较复杂,从略。 为保证配置目标的实现,应当为虚拟机配置双网卡。一块网卡使用Bridge Adapter模式
8、,既用于上网,同时可以让局域网内其他机器能够访问虚拟机共享目录。另一块网卡工作在Host-Only模式,专供宿主机访问虚拟机的共享文件。 2. 网卡与地址配置 首先在VirtualBox主界面中为虚拟机配置两块网卡,分别选择Bridge Adapter和Host-Only模式。 在linux系统中,传统上地址写在配置文件/etc/network/interfaces中,DNS地址写在/etc/resolv.conf中。但包括ubuntu在内的很多Linux发行版都包含了一个图形化的网络连接配置工具Network Manager。由它进行网络设置后,相关设置信息保存在/etc/NetworkMa
9、nager目录下的配置文件中。两种配置方法的相互关系比较复杂,为防止发生冲突,在配置网络前可将Network Manager删除。在任务栏菜单中选择“系统系统管理新力得软件包管理器”,然后在软件管理器界面左侧选择“网络”,在右侧选中“network-manager”,右键菜单中选择“标记以便彻底删除”,点击工具栏的“应用”即可完成删除。 也可以通过命令行模式删除: sudo apt-get -purge remove network-manager sudo apt-get -purge remove network-manager-gnome 删除Network Manager后,通过以下命
10、令用记事本打开网络地址配置文件:sudo gedit /etc/network/interfaces 对于未经配置的系统,文件通常只包括两行: auto lo iface lo inet loopback 这两行设置了环回接口,用于同一台主机的程序之间进行网络通信。在这两行之下加入下面的内容: # Bridged Connection to Wireless Lan Adapter auto eth0 iface eth0 inet static address 192.168.100.10 netmask 255.255.255.0 gateway 192.168.100.254 # Hos
11、t-Only Connection for File Sharing auto eth1 iface eth1 inet static address 192.168.56.10 netmask 255.255.255.0 gateway 192.168.56.1 每个接口设置的第1行是“auto 接口名”,接口由驱动程序创建,一般以太网卡接口名以eth开头,无线网卡以wifi开头,其后是编号。第2行设置地址的获取方式,静态地址为static,动态分配为dhcp。如果是静态地址,其后3行为ip地址、掩码和网关。上面配置中,eth0与宿主机无线网卡桥接,eth2是Host-Only模式的。对于e
12、th0,ip地址与宿主机在同一网段,子网掩码与网关和宿主机相同;对于eth1,ip地址与宿主机上VirtualBox虚拟网卡的ip地址在同一网段,默认网关就是这块虚拟网卡的ip。上述配置方式,适合于采用固定ip分配方式的局域网,如果宿主机是动态ip,则应将虚拟机的第一块网卡设置为NAT模式,上述配置eth0中static改为dhcp即可,其后的ip部分就不需要了。 接下来用以下命令打开DNS配置文件: sudo gedit /etc/resolv.conf 按如下格式添加DNS: nameserver xxx.xxx.xxx.xxx 文件修改完成后,用如下命令重启网络服务: sudo /etc
13、/init.d/networking restart四、挂载(Mount)数据空间 数据空间的作用是让虚拟机可以访问宿主机的目录。首先要在VirtualBox主界面中为虚拟机分配数据空间。 然后应在ubuntu的/mnt目录下创建子目录用于挂载。假设数据空间名称为dp,用于挂载的子目录名为shared,创建子目录和挂载可用下面命令完成:sudo mkdir /mnt/shared sudo mount -t vboxsf dp /mnt/shared 注意数据空间名称不要包含中文,也不能与挂载用的子目录同名。要实现自动挂载,可在记录文件系统信息的配置文件/etc/fstab中加入下面一行描述信
14、息:dp /mnt/shared vboxsf rw,gid=100,uid=1000,auto 0 0 如果需要挂载多个数据空间,只需改变描述信息中的前两项。在升级ubuntu前,最好将上述信息注释掉,待升级完成,重装增强功能后再恢复,否则会造成系统无法启动。五、配置samba文件共享 samba文件共享可以让宿主机访问虚拟机的目录。安装samba的命令为: sudo apt-get install samba sudo apt-get install smbfs 用下面命令创建将用于共享的文件夹arm,并赋予所有用户完全控制权限: mkdir /opt/arm chmod 777 /opt
15、/arm 一般来说/opt目录是供用户自由支配的,所以将共享文件夹放在这里。777代表所有用户里都对其具有读、写、运行权限。 然后创建一个用于网络访问的账户: sudo useradd sha 这个例子中用户名为sha,接下来将用户设定为samba认证用户: sudo gedit /etc/samba/smbusers 在打开的文件中添加一行: sha = network username 然后可以为sha用户授予访问samba的密码: sudo smbpasswd -a sha 如果以后要修改访问密码,也使用这条命令。下面代码将samba配置文件进行备份,然后打开供修改设定。 sudo cp
16、 /etc/samba/smb.conf /etc/samba/smb.conf_backup sudo gedit /etc/samba/smb.conf 找到这行: ; security = user 修改为: security = user username map = /etc/samba/smbusers 这样就改变了samba的安全设置,要求只有samba认证用户使用密码才能访问共享文件。在文件最底部加入这段共享文件夹设置:arm comment = Shared Folder with username and password path = /opt/arm public =
17、yes writable = yes available = yes browseable = yes valid users = sha create mask = 0766 directory mask = 0766 force user = nobody force group = nogroup 中是配置段的名字,一般与共享文件夹同名,comment是注释。path是要共享的目录,接下来4项是浏览和访问权限,一般填yes即可。valid users规定了能够访问这个目录的用户名,create mask和directory mask设置了由网络用户创建的文件和文件夹的权限,766表示创建
18、它的用户有读写运行权限,其他用户有读写权限。force user和force group设定了samba在管理共享文件夹时使用的用户名和组。对于服务器而言,应为低权限以保证安全,一般分别设置为nobody和 nogroup。对于开发用的系统而言,可以设置为日常登陆的用户名和users。 最后可以在配置文件的global段找到workgroup = MSHOME替换为: workgroup = WORKGROUP display charset = UTF-8 unix charset = UTF-8 dos charset = cp936 第一行声明了所在工作组的名称,方便windows主机访
19、问,下面几行设置了显示目录内容时的编码,用于支持汉语。全部配置完成后重启samba服务: sudo service smbd restart 根据刚才的配置,在samba运行时,如果用户以“ip地址”的形式访问共享文件夹,samba会要求输入用户名和密码。samba会向操作系统查询是否存在该用户,如果存在则比较该用户是否为samba的认证用户,如果是则验证密码。注意这个密码由samba保存,仅用于验证访问共享文件夹的权利,与用户登陆linux系统的密码不相干。注意在配置开始阶段仅仅进行用户了创建,这个用户并没有启用,更不能登陆系统,只是用于samba系统的认证。用户通过认证后,对共享文件夹的一
20、切操作都通过samba系统完成,samba系统此时以“force user”的身份进行操作,操作权限由“force group”决定。当登陆一次之后,windows系统会记录用户名和密码,以后不用输入了,如果更改配置需要换用户名或密码,可以在windows命令行下运行:net use * /del。六、界面设置 界面设置主要包括桌面、任务栏和系统快捷键。linux下快捷方式的名字叫“启动器”,可以将系统菜单中的项目拖动到桌面或任务栏上。在需要系统菜单中不存在的项目建立快捷方式时,可以在桌面右键菜单中选择“创建启动器”,在弹出对话框“名称”栏中输入快捷方式名称,在“命令”栏中输入用于打开相应程序
21、或文件夹的命令。对于程序,可以按Alt+F2快捷键列出已安装程序列表,从中可以查询到相应命令。对于目录可以输入:gnome-open /路径 或 nautilus /路径 快捷键可以通过菜单“系统”“首选项”“键盘快捷键”设置。右击任务栏上现有项目,可以将其解锁、移除,与Win7一致。要添加任务栏项目可在任务栏空白处点右键,选择“添加到面板”,在列表中选择相应内容。注意应当将“窗口列表(Window List)”加入任务栏,这样正在运行的程序才会像windows一样在任务栏上显示。 gnome桌面环境设置方法与windows很相似,但设置选项更多,更灵活。一番折腾后,桌面变成了下面这副充满恶趣
22、味的样子。 VirtualBox + Ubuntu配置备忘录(二)开发环境配置在系统安装安装并基本配置完成后,就需要安装一个开发环境,并且准备必要的头(.h)文件和库(.lib)文件,为了配置内核模块(驱动)开发环境,通常还需要重新编译内核。一、安装Code:Blocks Code:Blocks 是一个跨平台、开源的C、C+集成开发环境,功能比较完备,在Linux程序员中颇有好评。 Code:Blocks的界面是用跨平台的图形界面(GUI)库wxWidgets编写的,所以需要先行安装。可以在wxWidgets下载源码包,目前版本是2.8.12,下载后运行以下命令: #在下载目录下解压 bzip
23、2 -dc wxWidgets-2.8.12.tar.bz2 | tar -xvf - #进入源文件目录 cd ./wxWidgets-2.8.12 #执行配置脚本 ./configure 对于刚配置好的系统,通常最后一步会报错。因为wxWidgets是由图形库GTK+开发的,还需要安装。在“新立得包管理器”中搜索GTK+,选择libgtk2.0-dev,右键菜单中选择“标记以便安装”,系统会提示其他需要的软件包,确认后在工具栏中点“应用”,即进行安装。新版本ubuntu中已经没有新立得包管理器,可以在“ubuntu软件中心”中搜索 libgtk2.0-dev并安装,或执行命令: sudo a
24、pt-get install libgtk2.0-dev 安装完GTK+后,继续执行命令: ./configure #编译 make #安装 sudo make install #清理编译安装过程中的临时文件 make clean 至此安装完成,但还有一些wxWidgets组件并没有包含在源码包中,还需要网上更新。需要执行以下命令: #将wxWidgets网站的签名加入包管理器的证书库中 curl http:/apt.wxwidgets.org/key.asc | sudo apt-key add - 如果没有安装curl工具,需要使用如下命令安装: sudo apt-get install
25、curl #编辑软件更新下载服务器列表 sudo gedit /etc/apt/sources.list 在打开的文件底部加入这几行: # wxWidgets/wxPython repository at apt.wxwidgets.org deb http:/apt.wxwidgets.org/ #-wx main deb-src http:/apt.wxwidgets.org/ #-wx main 然后执行: sudo apt-get update 对不同的ubuntu发行版,需要下载不同版本的文件,所以要将#替换为系统发行版的代号(注意#前有一空格),可使用lsb_release -a命
26、令查看系统版本,其中Codename项的内容就是ubuntu发行版的代号,例如这次配置使用的10.10版代号为 maverick。目前wxWidgets对ubuntu只支持到代号为natty的11.4版,到如果使用了更高的发行版,#就只能填natty了。 上述配置完成后,就可以在Code:Blocks主页上下载最新安装文件的压缩包,这里下载的是带调试器10.05版。进入下载目录,用如下命令解压到当前文件夹中: bzip2 -dc codeblocks-10.05-1-debian-dbg-amd64.tar.bz2 | tar -xvf - 进入解压目录,可以发现压缩包中包含一系列.deb文件
27、,是Debian软件包管理系统的的安装文件。可以通过以下命令安装: sudo dpkg -i *.deb二、安装内核头文件 在旧版本内核中,开发内核模块只需使用内核头文件即可。输入以下命令即可查找并安装当前发行版对应的内核头文件: #在更新服务器上寻找当前内核版本对应的内核头文件 apt-cache search linux-headers-$(uname -r) #下载头文件 sudo apt-get install linux-headers-$(uname -r) 新版本已经不支持这种方式,应当按下文的描述编译内核。三、编译内核 众所周知,生成可执行的程序需要编译和链接两个步骤,在链接过
28、程中,编译好的各个目标文件与库文件结合在一起,形成最终的可执行文件。库文件实际是一组目标文件的组合,包含了系统函数的实现或调用接口,代码中调用了哪些系统提供的函数,就需要包含相应的库。对于新版内核模块开发来说,由于模块包含了内核提供的函数,就需要对应的内核目标文件完成链接,而这些目标文件要通过编译内核获得。1. 编译的准备 一般情况下,编译的内核源码版本与发行版内核版本相同即可,可以使用下列语句获取内核源码: sudo apt-get install linux-source-$(uname -r) 上述语句将到发行版开发商的更新服务器上取获取源码,但对于较老的发行版,可能已经不受开发商的支持
29、,源码无法在服务器上找到。此时可以首先升级当前发行版升级内核版本,再试图找到匹配的源码,或者在kernel.org上寻找相应版本的源码下载,如果编译的源码比当前内核版本高,则称为内核升级。 在本次配置中,将ubuntu发行版升级到了11.10,从kernel.org下载3.3.2版内核源码压缩包到/usr/src下。如果以前进行过内核编译,目录下会有一个linux文件夹,这是指向实际源码文件夹的符号链接,应首先将其删除: sudo rm -rf /usr/src/linux 然后将源码解压到相同目录里: bzip2 -dc /usr/src/linux-3.3.2.tar.bz2 | sudo
30、 tar -xvf - 源码解压后形成为新内核源码建立符号链接: cd /usr/src #进入文件夹 sudo ln -s linux-3.3.2 linux #建立符号链接 内核有数千个模块,并不是都需要的,同时为进行驱动开发,需要在内核中加入调试信息,需要对编译选项进行配置,为使用图形界面配置方式,应当首先安装c+编译器g+ 和qt: sudo apt-get install libqt4-dev sudo apt-get install g+ 如果不能安装,应当在更新管理器中选中相应的源。 然后进入源码文件夹,并开始配置: cd ./linux-3.3.2 sudo make xcon
31、fig 在弹出的配置对话框中,就可以进行相应模块的选择。对话框左边是描述模块分类的树形控件,选中某项,右边将显示具体模块列表和说明。当某选项前有“”时,说明可以指定这个或这组模块是否进入内核。选中某项,按y,中将出现,表示这个模块被编译进内核;按m,中出现表示模块将独立编译,供内核加载;按n,模块将不被编译。当然,有些选项不支持以独立模块方式编译。 注意图中被选中的选项不要编译,此外可以通过搜索功能找到DEBUG_SPINLOCK和DEBUG_STACKOVERFLOW选项,将其编译到内核中。为方便驱动开发,本次设置要将调试信息写入内核模块中,会是编译后的模块体积膨胀,可以在配置过程中,裁剪掉
32、大量不用的驱动。部分配置选项的具体含义可以参考这篇文章,注意内核版本不同,配置选项可能有部分变化。图形化配置完成后点保存,就生成了一个.config文件,这个文件是隐藏的。再将配置文件打开进行手工修改: sudo gedit .config 在文件中分别查找到: # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_DRIVER is not set 两项,改为: CONFIG_DEBUG_STACK_USAGE=y CONFIG_DEBUG_DRIVER=y 如果仅仅是一般的内核升级,可以使用如下配置命令,保持现有版本的内核配置: sudo
33、 make oldconfig2. 编译、安装与清理 保存配置文件后,就可以用下面的语句进行编译安装并清理临时文件,用#注释掉的语句是旧版内核编译时需要的,新版已经不用执行了。 #make dep sudo make bzImage sudo make modules sudo make modules_install sudo make install #sudo update-grub sudo make clean 配置完成后,可以重启电脑,将进入新内核中。如果新内核测试运行正常,则可以搜索并删除旧内核: dpkg -get-selections|grep linux 在列出的项中找到旧
34、内核名称#并删除: sudo apt-get remove # 本次配置中删除的是ubuntu 11.10发行版对应的内核linux-image-3.0.0-17-generic。四、测试开发环境配置结果 在任意目录(一般是/home的子目录)下建立一个hello.c文件,写入下列内容: #include #include MODULE_LICENSE(Dual BSD/GPL); static int hello_init(void) printk(KERN_ALERT Hello World); return 0; static void hello_exit(void) printk(K
35、ERN_ALERT Goodbye Earthman); module_init(hello_init); module_exit(hello_exit); 然后在同一目录下建立一个名为Makefile的文本文件,写入下列内容: obj-m := hello.o all: make -C /usr/src/*/ M=# modules clean: rm *.mod.c *.ko *.o ?odule*.* 注意在“make”和“rm”这两行的格式是:命令前有一个Tab,拷贝后直接保存不能运行!*用刚才编译内核时源码所在的目录代替,#用文件所在目录代替。然后在该目录下运行 sudo make
36、sudo insmod -s ./hello.ko sudo rmmod -s ./hello.ko sudo make clean 过片刻进入/var/log目录,打开syslog文件,在其中看到类似下面的内容就表明配置正确。 Apr 18 23:46:31 5d kernel: 1004.694564 Hello World 也可以使用命令读取日志信息: dmesg | tail -8 VirtualBox + Ubuntu配置备忘录(三)shell脚本在使用和维护Linux系统时,脚本的编写是必不可少的能力。shell(命令行)脚本可以看做是一个写有代码的源文件,按一定语法规则对若干Li
37、nux命令进行了组织,通过逻辑控制,完成预定的操作。脚本中的要素包括变量、表达式、命令、逻辑控制、函数、注释等。1. 基本格式与输出 脚本文件的开头一般有这样一行代码: #!/bin/bash 这行代码是告诉系统,使用何种脚本解释器来执行脚本,解释器bash是很常见的。通常编写脚本的规范要求指定解释器,但即使不写这一行,在很多系统下脚本也可执行。 在脚本中,单行输出命令为echo,例如: echo Hello World 多行输出语句有点像C+语言,形式如: cat 标号 多行语句 标号 表示将标号前的多行文字输出,一般标号使用字母全大写的单词,例如: cat HELP This script
38、 is used for test. Please check the content. HELP 这样就将夹在两个HELP中间的两行语句输出了。 建立一个脚本文件后,要将其赋予执行权限才能运行: chmod +x filename 权限设置完成后,通过命令行进入脚本所在目录,执行下面的命令就可以运行脚本: ./filename 上面两处命令中,filename是文件名,脚本文件扩展名一般为.sh。如果当前目录不是脚本文件所在目录,文件名还应加上绝对路径。 在执行脚本时,可以指定命令行参数,参数间用空格分隔,形式如: ./filename argument1 argument2 在脚本文件中,
39、在#后的整行语句都是注释语句。 如果一行中写了多条命令,需要用“;”分隔。2. 常量、变量与基本输入 在脚本文件中,常量不需要指定数据类型。字母与数字混合被视为字符串,数字直接写出即可,例如: echo abc123 #显示abc123 在脚本中,所谓变量相当于c语言中的宏,脚本执行时系统会将变量名替换为变量的值。变量的数据类型包括整数、小数、字符串等,变量名可以是字母、数字、下划线,变量名区分大小写。声明变量时同样不需要指定数据类型,但需要声明同时对其赋初值,初值可以是一个常量或其他变量,系统自动为变量指定类型,例如: a=123 b=10.5 str=abcd5678 变量名、等号、初始值
40、要连写,中间不能有空格。 在引用变量时,为不与普通字符串混淆,需要在变量前加$符号,例如: a=10 b=$a echo $a$b #显示1010 当变量需要与字符串连写时,为避免二义性,应当将变量名用包围,例如: echo $ath anniversary 基本输入语句为read,其后接一个新定义的变量名,例如: read a read后不能使用已有变量,必须在此新声明一个。3. 系统参数与命令行参数 为方便脚本编写,系统预定义了一些变量,保存了系统信息,常见的有以下几种: $PATH:系统搜索路径 $USER:当前用户 $SHELL:当前使用的命令行解释器名称 注意这些变量都是大写的。 在执行脚本时指定的命令行参数的内容和属性也由系统预定义的变量表示: $1、$2、:参数列表中的各个参数。 $#:参数的个数 $:全部参数组成的字符串 $*:各个参数组成的字符串数组 $