linux内核编程-qemu环境搭建
1.背景
最近想学习linux内核和驱动开发,但是不想买开发板,其实我觉得买了也买时间玩耍。以前读书的时候买过2440,后面到杭州买了6410和4412,买的时候兴致勃勃,买了之后新鲜了两天,由于各种原因还是放弃了,现在看到有虚拟环境,工作之余希望可以学习一下。
2.目的
深入学习linux内核和驱动。
3.虚拟机+Ubuntu
虚拟机可以装15/6;
ubuntu可以装16/18/20的,需要安装两块网卡都是NAT桥接。
虚拟机装了之后会覆盖原先的旧版本,但是原来的系统也可以使用。
4.Git
主要是为了代码管理,业界公认的。
5.qemu
5.1方式1:
系统镜像源自带,版本较低,但是入门够用。
5.1.1安装
sudo apt-get install qemu
5.1.2检测
qemu-system-arm -M help
5.2 方式2:
自己编译安装。
6. 测试镜像下载
https://github.com/wanglitao2020/doc
https://gitee.com/wang_litao/doc
7.qemu启动测试
7.1 zImage启动
touch boot.sh
gedit boot.sh
qemu-system-arm \
-M vexpress-a9 \
-m 512M \
-dtb ./vexpress-v2p-ca9.dtb \
-kernel ./zImage \
-append "root=/dev/mmcblk0 rw console=tty0" \
-sd rootfs.ext3
chmod +x boot.sh
./boot.sh
7.2 zImage 控制台启动
qemu-system-arm \
-M vexpress-a9 \
-m 512M \
-nographic \
-dtb ./vexpress-v2p-ca9.dtb \
-kernel ./zImage \
-append "root=/dev/mmcblk0 rw console=ttyAMA0" \
-sd rootfs.ext3
7.3 uboot引导启动
安装依赖包
sudo apt install net-tools
sudo apt install net-tools uml-utilities bridge-utils
ifconfig 查看网络
ens33:192.168.230.135
ens34:192.168.230.136
修改/etc/network/interfaces文件
auto lo
iface lo inet loopback
auto ens33
?auto br0
iface br0 inet dhcp
bridge_ports ens33
重启网络服务后ifconfig
br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.230.135 netmask 255.255.255.0 broadcast 192.168.230.255
inet6 fe80::20c:29ff:fed7:c2d9 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:d7:c2:d9 txqueuelen 1000 (Ethernet)
RX packets 7614 bytes 925743 (925.7 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 7461 bytes 10786796 (10.7 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
启动U-boot的脚本如下:
qemu-system-arm \
-M vexpress-a9 \
-m 512M \
-nographic \
-kernel ./u-boot \
-net nic,vlan=0 -net tap,vlan=0,ifname=tap0 \
-sd rootfs.ext3
uboot环境设置地址
=> setenv ipaddr 192.168.230.130
=> setenv serverip 192.168.230.135
=> ping 192.168.230.135
主机安装TFTP服务
$ sudo apt-get install tftp-hpa tftpd-hpa xinetd
在Ubuntu下修改配置文件:/etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/home/wit/tftpboot"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="-l -c -s"
sudo mkdir /home/wit/tftpboot
sudo chmod 777 /home/wit/tftpboot
sudo /etc/init.d/tftpd-hpa restart
启动加载
=> setenv ipaddr 192.168.230.130
=> setenv serverip 192.168.230.135
=> tftp 0x60003000 uImage
=> tftp 0x60500000 vexpress-v2p-ca9.dtb
=> bootm 0x60003000 - 0x60500000
7.4自动化引导
下载uboot源码
修改:include/configs/vexpress_common.h:
/*Netmask*/
196 #define CONFIG_IPADDR 192.168.230.130
197 #define CONFIG_NETMASK 255.255.255.0
198 #define CONFIG_SERVERIP 192.168.230.135
安装ARM交叉编译器,并编译u-boot:
安装编译器:
$ sudo apt install gcc-arm-linux-gnueabi gcc make libncurses-dev bison flex
配置
CROSS_COMPILE=arm-linux-gnueabi-
export CROSS_COMPILE
make vexpress_ca9x4_defconfig
make menuconfig 菜单选项配置
在Architecture select选项中选择:ARM architecture
设置bootcmd命令:
tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb;setenv bootargs 'root=/dev/mmcblk0 console=ttyAMA0';bootm 0x60003000 - 0x60500000;
编译
make
运行
u-boot拷贝到/home/wit/tftpboot目录
运行脚本启动u-boot看是否能自动引导uImage启动。
7.5 NFS文件系统
主机配置NFS服务:
sudo apt install nfs-kernel-server
在/etc/exports文件中添加:
/home/rootfs *(rw,sync,no_root_squash,no_subtree_check)
开启NFS服务:
sudo /etc/init.d/rpcbind restart
sudo /etc/init.d/nfs-kernel-server restart
主机制作文件系统
方式1
解压nfs.tar.gz
方式2
重新制作,参考附录
修改bootargs启动参数:
方式1
tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb;setenv bootargs 'root=/dev/nfs rw nfsroot=192.168.230.135:/home/wit/rootfs,proto=tcp,nfsvers=4,nolock init=/linuxrc ip=192.168.230.130 console=ttyAMA0';bootm 0x60003000 - 0x60500000;
方式2
配置uboot 重新编译
内核编译
修改Makefile:ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
make vexpress_defconfig
make zImage
apt install u-boot-tools
make uImage LOADADDR=0x60003000
make dtbs
文件拷贝
将生成的arch/arm/boot/uImage和arch/arm/boot/dts/vexpress-v2p-ca9.dtb拷贝到/home/wit/tftpboot目录下,使用下面的命令启动内核:
qemu-system-arm \
-M vexpress-a9 \
-m 512M \
-nographic \
-kernel ./u-boot \
-net nic,vlan=0 -net tap,vlan=0,ifname=tap0 \
-sd rootfs.ext3
附录
制作NFS文件系统
编译busybox
nfs
Linux System Utilities --->
[*] mount (30 kb)
[*] Support mounting NFS file systems on Linux < 2.6.23
创建rootfs目录
>>mkdir etc
>>cd etc
>>vim inittab
::sysinit:/etc/init.d/rcS // 执行rcS脚本
#::respawn:-/bin/sh
#tty2::askfirst:-/bin/sh
#::ctrlaltdel:/bin/umount -a -r
console::askfirst:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
>>vim init.d/rcS
#! /bin/sh
PATH=/sbin:/bin:/user/sbin:/usr/bin
LD_LIBRARY_PATH=/lib
export PATH LD_LIBRARY_PATH
mount -a // 挂载根文件系统 fstab
mkdir -p /dev/pts
mount -t devpts devpts dev/pts
mdev -s
mkdir -p /var/lock
echo "......"
>>vim fstab
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs default 0 0
sysfs /sys sysfs default 0 0
tmpfs /dev tmpfs default 0 0
var /dev tmpfs default 0 0
ramfs /dev ramfs default 0 0
>>vim profile
PS1='xiami@vexpress:\w #'
export PS1
也可以在~/.bashrc中修改或设置PS1
启动流程:
Linux内核启动之后,挂载根文件系统
开启init进程,bootargs init=/linuxrc,启动第一个用户进程
在用户进程中读取inittab脚本,
构建其他目录
>> cd rootfs
>>mkdir proc mnt tmp sys root\
制作SD文件系统
下载busybox工具
从https://busybox.net/downloads/下载最新的busybox。
同样,建议在windows系统下使用迅雷下载,先找到合适的busybox版本,再用右键,选择用迅雷下载,这样速度会很快;
解压busybox
tar -xvf busybox-1.31.1.tar.bz2
配置并编译busybox
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig
编译选择使用glibc动态库,因为静态库可能会出现一些未知的问题
>> make menuconfig
Settings --->
Build Options --->
[ ] Build static binary (no shared libs)
默认的安装目录是./_install,如果需要指定安装目录,可以在下边修改:
Settings --->
Installation Options ("make install" behavior)
(./_install) Destination path for 'make install'
>> make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
安装
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- install
提示下边信息,表示安装成功:
--------------------------------------------------
You will probably need to make your busybox binary
setuid root to ensure all configured applets will
work properly.
查看
>> ls _install/
bin linuxrc sbin usr
或者直接使用CONFIG_PREFIX指定安装目录:
>>make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- CONFIG_PREFIX=/.../rootfs/ install
Tip 提前设置好编译默认值 编译安装过程中,一直输入ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-比较麻烦,可以在Makefile中设置好默认值;
修改Makefile:
>> vim Makefile
ARCH = arm
CROSS_COMPILE = arm-linux-gnueabi-
之后的编译、安装命令就简单了:
>>make
>> make install
创建根目录
将busybox编译生成的_install目录下的文件全部拷贝到根文件系统目标rootfs/目录:
>> mkdir rootfs
# cp /.../busybox-1.29.3/_install/* rootfs/ -rfd
也可以在指定busybox的安装目录直接安装:
# make CONFIG_PREFIX=/.../rootfs/ install
添加glibc库
在根文件系统中添加加载器和动态库:
>> mkdir rootfs/lib
#>>cp /usr/arm-linux-gnueabi/lib/* rootfs/lib/ -rfp
静态创建设备文件
>> mkdir rootfs/dev
>> cd rootfs/dev
>> mknod -m 666 tty1 c 4 1
>> mknod -m 666 tty2 c 4 2
>> mknod -m 666 tty3 c 4 3
>> mknod -m 666 tty4 c 4 4
>> mknod -m 666 console c 5 1
>> mknod -m 666 null c 1 3
制作SD卡文件系统镜像
生成一个空的SD卡镜像:
>> dd if=/dev/zero of=rootfs.ext3 bs=1M count=32
32+0 records in
32+0 records out
33554432 bytes (34 MB, 32 MiB) copied, 0.0236764 s, 1.4 GB/s
将SD卡格式化为exts文件系统:
mkfs.ext3 rootfs.ext3
mke2fs 1.42.13 (17-May-2015)
Discarding device blocks: done
Creating filesystem with 32768 1k blocks and 8192 inodes
Filesystem UUID: 51ab1063-a137-48e5-a6f4-4552dad3b898
Superblock backups stored on blocks:
8193, 24577
Allocating group tables: done
Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done
将rootfs烧写到SD卡:
>> sudo mount -t ext3 rootfs.ext3 /mnt -o loop
>> sudo cp -rf rootfs/* /mnt/
>> sudo umount /mnt
Tip 在开发过程中,如果需要修改SD卡中的内容,可以将SD卡的镜像rootfs.ext3挂载到/mnt目录下,直接操作/mnt来修改;
>> sudo mount -t ext3 rootfs.ext3 /mnt -o loop
>> cp rootfs.ext3 ~/qemu
参考链接
环境搭建 老师博客
|