完善基于qemu的linux开发环境

前言

本文是搭建基于qemu的linux开发环境的后续,之前搭建的环境使用时还有一些不便利的地方,以及内核配置上的些许遗漏。因此对之前搭建的环境做一些完善,本文则是记录这个完善过程。

1 完善根文件系统

前文文末指出通过busybox构建的最小文件系统缺少一些配置文件,主要是这么几个文件:/etc/inittab/etc/fstab/etc/profile/etc/init.d/rcS(rcS已经创建,不过这里会做一些修改)。接下来,给出这些文件的内容:

① /etc/inittab

# /etc/inittab
::sysinit:/etc/init.d/rcS
ttyAMA0::askfirst:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r

② /etc/fstab

#device       mount-point	type	options		dump	fsck order
proc          /proc         proc	defaults    0       0
sysfs         /sys          sysfs   defaults	0       0
tmpfs         /dev          tmpfs   defaults	0       0

③ /etc/profile

# 配置shell环境的命令提示符:用户名@主机名:当前路径 #
PS1='lenny@vexpress:\w # '
export PS1

④ /etc/init.d/rcS

#!bin/sh

# mount fs according to fstab
mount -a

# mdev相当于嵌入式版本的udev
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s

以上几个文件的格式以及含义网上有很多资料讲解,很容易查到,因此这里只给出内容,其它不再多说。

⑤ 拷贝动态库

除此上述的几个配置文件外,还需要将工具链所带的动态库拷贝到根文件系统的lib目录下。这是为什么呢?当我们编写了一个程序如下:

/* a.c */
#include <stdio.h>

int main()
{
	printf("hello world\n");
	return 0;
}

一个很简单的程序,使用交叉编译工具链编译(默认动态链接):

arm-linux-gnueabi-gcc a.c

然后再qemu运行的linux系统上执行:

./a.out

会提示如下信息:

-/bin/sh: ./a.out: not found

这是因为当前根文件系统的lib目录下还没有动态链接器以及各自动态库,linux找不到动态链接器自然也就无法加载动态链接的可执行文件了。反过来,如果我们静态链接:

arm-linux-gnueabi-gcc -static a.c -o a_static

则可以在qemu上运行可执行文件a_static。这又是为什么呢?更多关于程序链接的知识,可以参考我的另外一篇博客:计算机系统基础摘记——程序的链接

至此,我们搞清楚了为什么需要动态库。现在我们将交叉编译工具链自带的动态库拷贝过来即可:

cp /usr/arm-linux-gnueabi/lib/*.so* ./ -d

值得注意的是,拷贝的具体路径需要根据自己的开发环境来确定;拷贝指令中 的-d选项的作用是拷贝软链接时,保持软链接,而不是去拷贝软链接指向的文件(避免重复拷贝真正的动态库文件)。

2 配置静态IP

我的Ubuntu当前使用的是动态IP,重新开机后IP可能会变化,因此每次使用u-boot启动kernel时可能需要修改环境变量(服务器IP变了),这样非常麻烦,因此决定为Ubuntu设置静态IP。

设置静态IP主要是修改配置文件/etc/network/interfaces。这个文件在配置qemu的网络时已经修改过,当前内容如下:

# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback

auto ens33
auto br0
iface br0 inet dhcp
bridge_ports ens33

配置静态IP后内容如下:

# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback

auto br0
iface br0 inet static
address 192.168.0.117
netmask 255.255.255.0
broadcast 192.168.0.255
gateway 192.168.0.1
bridge_ports ens33

auto ens33

配置完后需要重启网卡或重启计算机,以使配置生效。

3 配置DNS服务器

之前我们使用动态IP时,IP地址由DHCP(动态主机配置协议)服务器分配。除了IP地址外,DHCP还会给主机分配DNS服务器(告诉主机域名服务器的IP),而我们设置了静态IP后,主机就不会向DHCP服务器请求服务了,换句话说现在没人告诉主机域名服务器的IP了。实际测试也发现,设置完静态IP后,执行ping www.baidu.com,会提示unkown host

这个问题的由来很清楚,解决方法就是自己设置DNS的IP。不过,值得一提的是,网上流传的一些设置DNS的方法在Ubuntu18.04.2已经失效了。比如:

  • 修改/etc/network/interfaces
    在/etc/network/interfaces文件中添加一行:dns-nameservers IP。实测,该方法无效。
  • 修改/etc/resolvconf/resolv.conf.d/base
    在/etc/resolvconf/resolv.conf.d/base文件中添加一行nameserver IP。在修改这个文件后进行保存时提示如下错误:在这里插入图片描述

上述方法在更老版本的Ubuntu中是有效的,至于上述配置方式从哪个版本开始被放弃的,我没有查过。那么,在Ubuntu18.04.2中如何配置DNS的IP呢?我在参考文献[1]中找到了答案:修改配置文件/etc/systemd/resolved.conf,将DNS配置项设置为:

# 国内移动、电信和联通通用的DNS(国内用速度快、稳定)
DNS=114.114.114.114
# Google提供的DNS(全球通用)
DNS=8.8.8.8

修改完配置文件后,重启相关服务:

systemctl restart systemd-resolved.service

执行systemd-resolve --status查看配置结果,可以发现,此时DNS的IP已经变为我们刚才设置的。再次执行ping www.baidu.com,可以ping通。

4 kernel的热插拔相关配置

修改完静态IP后,需要修改u-boot中相关环境变量,将serverip改为上文设置的静态IP,同时给内核传递的参数bootargs中相关IP也要改变。然后,从qemu启动u-boot,进而启动内核,内核能够顺利启动,不过执行rcS中的echo /sbin/mdev > /proc/sys/kernel/hotplug时出错,错误信息如下:

can't create /proc/sys/kernel/hotplug: nonexistent directory

一番搜索后,在参考文献[2]中发现了答案:配置CONFIG_UEVENT_HELPER。这个配置项具体位于menuconfig的:Device Drivers ⇒ Generic Driver Options下。此外,我们可以在选中该选项的同时,设置配置项CONFIG_UEVENT_HELPER_PATH/sbin/mdev,这样就可以不用执行rcS中echo语句了。

至于为什么要将/sbin/mdev的位置告知给kernel,根源在kernel实现热插拔的方式。热插拔有两种实现方式,一种是内核通过netlink向用户空间广播uevent消息,用户空间的进程udev根据收到的消息执行一些动作;另一种是内核空间启动一个用户空间进程,通过给进程传递环境变量的方式传递uevent消息,然后被启动的进程根据消息执行一些动作,以处理热插拔事件(busybox的mdev适用于此方式)。既然需要内核启动mdev,那么我们自然要将mdev的pathname告诉内核。

另外,对于/proc/sys/kernel/hotplug不存在的问题,网上有说要配置CONFIG_HOTPLUG,这个解决方法可能适合版本较旧的内核,在我使用的5.4.26版本的内核中,这个配置项已经被移除了,且原先这个配置项影响的代码总是会被编译(相当于这个配置项总是被选中)。

参考文献

[1] Ubuntu 18.04 永久修改DNS的方法
[2] genkernel init: Can’t create /proc/sys/kernel/hotplug

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值