[授权发表]利用 qemu 模拟嵌入式系统制作全过程

2023-05-16

利用qemu模拟嵌入式系统制作全过程

by Pingbo Wen of TinyLab.org
2013/08/31

最初发表:泰晓科技 – 聚焦嵌入式 Linux,追本溯源,见微知著!
原文链接:利用 qemu 模拟嵌入式系统制作全过程
评论说明:为更好地聚合大家的讨论,请到上面原文的评论区回复。


这篇文章将介绍如何用 Qemu 来搭建一个基于 ARM 的嵌入式 Linux 系统。通过该文章可以学习到如何配置和交叉编译 Kernel,如何配置 Busybox 并编译,如何制作 Initramfs,如何制作根文件系统,如何定制自己的 Uboot,如何通过 Uboot 向 Kernel 传递参数等。开始干活!

零、环境搭建

在实现我们的目标之前,我们需要搭建自己的工作环境。在这里,假设你的主机上已经有gcc本地编译环境,并运行Ubuntu 12.10。但是这并不影响在其他的linux平台上进行,只要修改一下对应的命令就可以了。

首先,我们需要下载一个ARM交叉工具链。你可以在网上下载源码自己编译,也可以下载已经编译好的工具链。在工具链中有基本的ARM编译工具,比如:gcc, gdb, addr2line, nm, objcopy, objdump等。可能你会问,这些工具本机不是已经有了么?如果不出意外,我想你的主机应该是x86架构的。不同的架构,有不同的指令集,你不能拿一个x86的执行文件放到一个ARM机器上执行。所以我们需要一个能够在x86架构上生成ARM可执行程序的GCC编译器。有很多预先编译好的ARM工具链,这里使用的是CodeSourcery[1]。更多关于toolchain的信息可以在elinux.org找到[2]。下载下来后,直接解压,放到某个目录,然后配置一下PATH环境变量,这里是这样配置的:


export PATH=~/arm-2013.05/bin:$PATH
  

配置完ARM交叉工具链后,我们需要下载一些源码,并安装一些软件。 命令如下: ``` # install qemu sudo apt-get install qemu qemu-kvm qemu-kvm-extras qemu-user qemu-system # install mkimage tool sudo apt-get install uboot-mkimage # install git sudo apt-get install git # prepare related directory mkdir -pv ~/armsource/{kernel,uboot,ramfs,busybox} # download latest kernel stable code to kernel dir git clone http://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git ~/armsource/kernel # download latest u-boot code to uboot dir git clone git://git.denx.de/u-boot.git ~/armsource/uboot # download latest busybox code to busybox dir git clone git://busybox.net/busybox.git ~/armsource/busybox ```

一、配置kernel

环境搭建完后,我们就正式进入主题了。现在我们需要配置kernel源码,编译,并用qemu运行我们自己编译的kernel。这样我们就能够对我们的kernel进行测试,并做出对应的修改。

进入kernel源码目录,我们需要找最新的kernel稳定版本。在写这篇文章的时候,最新的稳定版本是3.10.10。我们可以通过git切换到3.10.10。由于我们编译的内核需要运行在ARM上,所以我们应该到arch/arm/configs下找到对应我们设备的kernel配置文件。但是我们没有实际意义上的设备,而是用qemu模拟的设备,所以我们应该选择qemu能够模拟的设备的配置文件。这里我们选择常用的versatile_defconfig。 对应的命令如下: ``` cd ~/armsource/kernel # checkout a tag and create a branch git checkout v3.10.10 -b linux-3.10.10 # create .config file make versatile_defconfig ARCH=arm ```

配置完了,我们就可以编译了。编译的时候,我们可以用多个线程来加速编译,具体用多少个就要看你主机的配置了。这里我们用12个线程编译,命令如下:


make -j12 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
  

注意,如果交叉编译环境没有配置好,这个地方会提示找不到对应的gcc编译器。这里-j12是指定编译线程为12个,ARCH是指定目标架构为arm,所用的交叉编译器arm-none-linux-gnueabi-。

OK,kernel已经编译好了,那么我们需要用qemu把它跑起来。关于qemu的具体使用,请看qemu的官方文档[3],这里直接给出命令:


qemu-system-arm -M versatilepb -kernel arch/arm/boot/zImage -nographic
  

这里-M是指定模拟的具体设备型号,versatile系列的pb版本,-kernel指定的是对应的内核,-nographic是把qemu输出直接导向到当前终端。

好,命令成功执行了。但是,好像没有任何有效输出。我们通过C-a x来退出qemu。编译的kernel好像不怎么好使,配置文件肯定有问题。打开.config配置文件,发现传递给kernel的参数没有指定console,难怪没有输出。我们定位到CMDLINE,并加入console参数:


CONFIG_CMDLINE="console=ttyAMA0 root=/dev/ram0"
  

保存.config,重新编译kernel,并用qemu加载。现在终于有输出了。如果不出意外,kernel应该会停在找不到根文件系统,并跳出一个panic。为什么会找不到根文件系统?因为我们压根就没有给它传递过,当然找不到。

那现在是不是应该制作我们自己的根文件系统了。先别急,为了让后面的路好走一点,我们这里还需对内核进行一些配置。首先,我们需要用ARM EABI去编译kernel,这样我们才能让kernel运行我们交叉编译的用户态程序,因为我们所有的程序都是用gnueabi的编译器编译的。具体可以看wikipedia相关页面[4],你也可以简单的理解为嵌入式的ABI。其次,我们需要把对kernel module的支持去掉,这样可以把相关的驱动都编译到一个文件里,方便我们之后的加载。

当然,你可以使能kernel的debug选项,这样就可以调试内核了,并打印很多调试信息。这里就不再说了,如果感兴趣,可以看我之前写的关于kernel调试的文章[5]。

总结起来,这一次我们对.config做了如下修改: ``` # CONFIG_MODULES is not set CONFIG_AEABI=y CONFIG_OABI_COMPAT=y CONFIG_PRINTK_TIME=y CONFIG_EARLY_PRINTK=y CONFIG_CMDLINE="earlyprintk console=ttyAMA0 root=/dev/ram0" ```

二、通过busybox制作initramfs镜像

如果你注意到了之前传递给kernel的参数,你会发现有一个root=/dev/ram0的参数。没错,这就是给kernel指定的根文件系统,kernel检查到这个参数的时候,会到指定的地方加载根文件系统,并执行其中的init程序。这样就不会出现刚才那种情况,找不到根文件系统了。

我们的目标就是让kernel挂载我们的ramfs根文件系统,并且在执行init程序的时候,调用busybox中的一个shell,这样我们就有一个可用的shell来和系统进行交互了。

整个ramfs中的核心就是一个busybox可执行文件。busybox就像是一把瑞士军刀,可以把很多linux下的命令(比如:cp, rm, whoami等)全部集成到一个可执行文件[6]。这为制作嵌入式根文件系统提供了很大的便利,开发者不用单独编译每一个要支持的命令,还不用考虑库的依赖关系。基本上每一个制作嵌入式系统的开发者的首选就是busybox。

busybox也是采用Kconfig来管理配置选项,所以配置和编译busybox和kernel没有多大区别。busybox很灵活,你可以自由取舍你想要支持的命令,并且还可以添加你自己写的程序。在编译busybox的时候,为了简单省事,我们这里采用静态编译,这样就不用为busybox准备其他libc,ld等依赖库了。

具体命令如下: ``` cd ~/armsource/busybox # using stable version 1.21 git checkout origin/1_21_stable -b busybox-1.21 # using default configure make defconfig ARCH=arm # compile busybox in static make menuconfig make -j12 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- ``` 编译完后,我们就得到一个busybox静态链接的文件。

接下来,我们需要一个init程序。这个程序将是kernel执行的第一个用户态的程序,我们需要它来产生一个可交互的shell。在桌面级别的linux发行版本,使用的init程序一般是System V init(传统的init),upstart(ubuntu),systemd(fedora)等。busybox也带有一个init程序,但是我们想自己写一个。既然自己写,那有两种实现方式,用C和libc实现,或者写一个shell脚本。

为了简单,这里选择后者,具体脚本如下: ``` #!/bin/sh echo echo "###########################################################" echo "## THis is a init script for initrd/initramfs ##" echo "## Author: wengpingbo@gmail.com ##" echo "## Date: 2013/08/17 16:27:34 CST ##" echo "###########################################################" echo

PATH="/bin:/sbin:/usr/bin:/usr/sbin"

if [ ! -f “/bin/busybox” ];then
echo “cat not find busybox in /bin dir, exit”
exit 1
fi

BUSYBOX="/bin/busybox"

echo “build root filesystem…”
$BUSYBOX --install -s

if [ ! -d /proc ];then
echo “/proc dir not exist, create it…”
$BUSYBOX mkdir /proc
fi
echo “mount proc fs…”
$BUSYBOX mount -t proc proc /proc

if [ ! -d /dev ];then
echo “/dev dir not exist, create it…”
$BUSYBOX mkdir /dev
fi

echo “mount tmpfs in /dev…”

$BUSYBOX mount -t tmpfs dev /dev

$BUSYBOX mkdir -p /dev/pts
echo “mount devpts…”
$BUSYBOX mount -t devpts devpts /dev/pts

if [ ! -d /sys ];then
echo “/sys dir not exist, create it…”
$BUSYBOX mkdir /sys
fi
echo “mount sys fs…”
$BUSYBOX mount -t sysfs sys /sys

echo “/sbin/mdev” > /proc/sys/kernel/hotplug
echo “populate the dev dir…”
$BUSYBOX mdev -s

echo “drop to shell…”
$BUSYBOX sh

exit 0

</p>
<p>
我们把这个脚本保存在~/armsource目录下。在这个脚本中,我们通过busybox --install -s来构建基本文件系统,挂载相应的虚拟文件系统,然后就调用busybox自带的shell。
</p>
<p>
现在我们已经编译好了busybox,并准备好了相应的init脚本。我们需要考虑根文件系统的目录结构了。kenel支持很多种文件系统,比如:ext4, ext3, ext2, cramfs, nfs, jffs2, reiserfs等,还包括一些伪文件系统: sysfs, proc, ramfs等。而在kernel初始化完成后,会尝试挂载一个它所支持的根文件系统。根文件系统的目录结构标准是FHS,由一些kernel开发者制定,感兴趣的可以看wikipedia相关页面[7]。
</p>
<p>
由于我们要制作一个很简单的ramfs,其中只有一个busybox可执行文件,所以我们没必要过多的考虑什么标准。只需一些必须的目录结构就OK。这里,我们使用的目录结构如下:
<pre>
├── bin
│   ├── busybox
│   └── sh ->busybox
├── dev
│   └── console
├── etc
│   └── init.d
│       └── rcS
├── init
├── sbin
└── usr
    ├── bin
    └── sbin
</pre>
</p>
<p>
你可以通过如下命令来创建这个文件系统:

cd ~/armsource/ramfs
mkdir -pv bin dev etc/init.d sbin user/{bin,sbin}
cp ~/armsource/busybox/busybox bin/
ln -s busybox bin/sh
mknod -m 644 dev/console c 5 1
cp ~/armsource/init .
touch etc/init.d/rcS
chmod +x bin/busybox etc/init.d/rcS init

</p>
<p>
现在我们有了基本的initramfs,万事具备了,就差点东风了。这个东风就是怎样制作intramfs镜像,并让kernel加载它。
</p>
<p>
在kernel文档中,对initramfs和initrd有详细的说明[8][9]。initramfs其实就是一个用gzip压缩的cpio文件。我们可以把initramfs直接集成到kernel里,也可以单独加载initramfs。在kernel源码的scripts目录下,有一个gen_initramfs_list.sh脚本,专门是用来生成initramfs镜像和initramfs list文件。你可以通过如下方式自动生成initramfs镜像:
<pre>
sh scripts/gen_initramfs_list.sh -o ramfs.gz ~/armsource/ramfs
</pre>
</p>
<p>
然后修改kernel的.config配置文件来包含这个文件:
<pre>
CONFIG_INITRAMFS_SOURCE="ramfs.gz"
</pre>
重新编译后,kernel就自动集成了你制作的ramfs.gz,并会在初始化完成后,加载这个根文件系统,并产生一个shell。
</p>
<p>
你也可以用gen_initramfs_list.sh脚本生成一个列表文件,然后CONFIG_INITRAMFS_SOURCE中指定这个列表文件。也可以把你做的根文件系统自动集成到kernel里面。命令如下:

sh scripts/gen_initramfs_list.sh ~/armsource/ramfs > initramfs_list

对应的内核配置:CONFIG_INITRAMFS_SOURCE="initramfs_list"
</p>
<p>
但是这里并不打算这么做,我们自己手动制作initramfs镜像,然后外部加载。命令如下:
<pre>
cd ~/armsource/ramfs
find . | cpio -o -H newc | gzip -9 &gt; ramfs.gz
</pre>
选项-H是用来指定生成的格式。
</p>
<p>
手动生成ramfs.gz后,我们就可以通过qemu来加载了,命令如下:
<pre>
qemu-system-arm -M versatilepb -kernel arch/arm/boot/zImage -nographic -initrd ramfs.gz
</pre>
</p>
<p>
现在我们的系统起来了,并且正确执行了我们自己写的脚本,进入了shell。我们可以在里面执行基本常用的命令。是不是有点小兴奋。
</p>
<h2>三、配置物理文件系统,切换根文件系统</h2>
<p>
不是已经配置了根文件系统,并加载了,为什么还需要切换呢?可能你还沉浸在刚才的小兴奋里,但是,很不幸的告诉你。现在制作的小linux系统还不是一个完全的系统,因为没有完成基本的初始化,尽管看上去好像已经完成了。
</p>
<p>
在linux中initramfs和initrd只是一个用于系统初始化的小型文件系统,通常用来加载一些第三方的驱动。为什么要通过这种方式来加载驱动呢?因为由于版权协议的关系,如果要把驱动放到kernenl里,意味着你必须要开放源代码。但是有些时候,一些商业公司不想开源自己的驱动,那它就可以把驱动放到initramfs或者initrd。这样既不违背kernel版权协议,又达到不开源的目的。也就是说在正常的linux发行版本中,kernel初始化完成后,会先挂载initramfs/initrd,来加载其他驱动,并做一些初始化设置。然后才会挂载真真的根文件系统,通过一个switch_root来切换根文件系统,执行第二个init程序,加载各种用户程序。在这中间,linux kernel跳了两下。
</p>
<p>
既然他们跳了两下,那我们也跳两下。第一下已经跳了,现在的目标是制作物理文件系统,并修改initramfs中的init脚本,来挂载我们物理文件系统,并切换root文件系统,执行对应的init。
</p>
<p>
为了省事,我们直接把原先的initramfs文件系统复制一份,当作物理根文件系统。由于是模拟,所以我们直接利用dd来生成一个磁盘镜像。具体命令如下:
<pre>
dd if=/dev/zero of=~/armsource/hda.img bs=1 count=10M
mkfs -t ext2 hda.img
mount hda.img /mnt
cp -r ~/armsource/ramfs/* /mnt
umount /mnt
</pre>
</p>
<p>
这样hda.img就是我们制作的物理根文件系统,ext2格式。现在我们需要修改原先在initramfs中的init脚本,让其通过busybox的switch_root功能切换根文件系统。这里需要注意的是,在切换根文件系统时,不能直接调用busybox的switch_root,而是需要通过exec来调用。这样才能让最终的init进程pid为1。
</p>
<p>
修改后的init脚本如下:

#!/bin/sh
echo
echo “###########################################################”
echo “## THis is a init script for sd ext2 filesystem ##”
echo “## Author: wengpingbo@gmail.com ##”
echo “## Date: 2013/08/17 16:27:34 CST ##”
echo “###########################################################”
echo

PATH="/bin:/sbin:/usr/bin:/usr/sbin"

if [ ! -f “/bin/busybox” ];then
echo “cat not find busybox in /bin dir, exit”
exit 1
fi

BUSYBOX="/bin/busybox"

echo “build root filesystem…”
$BUSYBOX --install -s

if [ ! -d /proc ];then
echo “/proc dir not exist, create it…”
$BUSYBOX mkdir /proc
fi
echo “mount proc fs…”
$BUSYBOX mount -t proc proc /proc

if [ ! -d /dev ];then
echo “/dev dir not exist, create it…”
$BUSYBOX mkdir /dev
fi

echo “mount tmpfs in /dev…”

$BUSYBOX mount -t tmpfs dev /dev

$BUSYBOX mkdir -p /dev/pts
echo “mount devpts…”
$BUSYBOX mount -t devpts devpts /dev/pts

if [ ! -d /sys ];then
echo “/sys dir not exist, create it…”
$BUSYBOX mkdir /sys
fi
echo “mount sys fs…”
$BUSYBOX mount -t sysfs sys /sys

echo “/sbin/mdev” > /proc/sys/kernel/hotplug
echo “populate the dev dir…”
$BUSYBOX mdev -s

echo “dev filesystem is ok now, log all in kernel kmsg” >> /dev/kmsg

echo “you can add some third part driver in this phase…” >> /dev/kmsg
echo “begin switch root directory to sd card” >> /dev/kmsg

$BUSYBOX mkdir /newroot
if [ ! -b “/dev/mmcblk0” ];then
echo “can not find /dev/mmcblk0, please make sure the sd
card is attached correctly!” >> /dev/kmsg
echo “drop to shell” >> /dev/kmsg
$BUSYBOX sh
else
$BUSYBOX mount /dev/mmcblk0 /newroot
if [ $? -eq 0 ];then
echo “mount root file system successfully…” >> /dev/kmsg
else
echo “failed to mount root file system, drop to shell” >> /dev/kmsg
$BUSYBOX sh
fi
fi

the root file system is mounted, clean the world for new root file system

echo “” > /proc/sys/kernel/hotplug
$BUSYBOX umount -f /proc
$BUSYBOX umount -f /sys
$BUSYBOX umount -f /dev/pts

$BUSYBOX umount -f /dev

echo “enter new root…” >> /dev/kmsg
exec $BUSYBOX switch_root -c /dev/console /newroot /init

if [ $? -ne 0 ];then
echo “enter new root file system failed, drop to shell” >> /dev/kmsg
$BUSYBOX mount -t proc proc /proc
$BUSYBOX sh
fi

</p>
<p>
现在我们可以通过qemu来挂载hda.img,为了简单,我们这里把这个设备虚拟为sd卡,这也是为什么上面的init脚本挂载物理根文件系统时,是找/dev/mmcblk0了。具体命令如下:
<pre>
qemu-system-arm -M versatilepb -kernel arch/arm/boot/zImage -nographic -initrd ramfs.gz -sd hda.img
</pre>
</p>
<p>
如果不出意外,你可以看到这个自己做的linux系统,通过调用两个init脚本,跳到最终的hda.img上的文件系统。
</p>
<h2>四、配置Uboot,加载kernel</h2>
<p>
可能到这里,你觉得,终于把整个流程走了一遍了。但是,还差一环。之前我们都是通过qemu来直接加载我们的kernel,initramfs和物理镜像,但是在真真的嵌入式设备,这些加载过程都需要你好好考虑。那么在这一节,我们借助uboot来模拟加载过程。
</p>
<p>
我们的目标是让uboot来加载kernel,initramfs,并识别qemu虚拟的sd卡设备。这里我们通过tftp来向uboot传递kernel和initramfs镜像。既然要依靠uboot来加载系统镜像,那么需要按照uboot的镜像格式制作加载的镜像。而mkimage工具,就是干这活的。在制作uboot镜像时,我们需要指定镜像类型,加载地址,执行地址等,制作uboot版的initramfs命令如下:
<pre>
mkimage -A arm -O linux -T ramdisk -C none -a 0x00808000 -e 0x00808000 -n ramdisk -d ramfs.gz ramfs-uboot.img
</pre>
其中-a 和 -e分别是指定加载定制和执行地址
</p>
<p>
而kernel的uboot版就不需要这么手动生成了,在编译kernel的时候,可以通过make uImage来制作uboot格式镜像,默认的加载地址是0x00008000,你也可以通过LOADADDR指定你自己的加载地址,这里用默认的。
</p>
<p>
镜像准备好之后,需要把这两个镜像拷贝到一个指定的目录,这样在用tftp传输的时候,能够找到对应的镜像。这里假设拷贝到~/armsource/tftp目录下。
</p>
<p>
下一步,我们需要交叉编译uboot。在编译之前,我们需要对uboot进行一些配置。由于我们使用的是versatilepb,它对应的配置文件在include/configs/versatile.h中,这里对这个文件的修改如下:

#define CONFIG_ARCH_VERSATILE_QEMU
#define CONFIG_INITRD_TAG
#define CONFIG_SYS_PROMPT "myboard > "
#define CONFIG_BOOTCOMMAND
“sete ipaddr 10.0.2.15;”
“sete serverip 10.0.2.2;”
“set bootargs ‘console=ttyAMA0,115200 root=/dev/mmcblk0’;”
“tftpboot 0x00007fc0 uImage;”
“tftpboot 0x00807fc0 ramfs-uboot.img;”
“bootm 0x7fc0 0x807fc0”

其中ARCH_VERSATILE_QEMU是为了让uboot为了适应qemu做一些配置上的调整。<br />
INITRD_TAG是让uboot通过tag_list给kernel传递initramfs的地址,如果没有这个配置选项,kernel是找不到uboot传给他的initramfs。<br />
SYS_PROMPT是指定uboot的命令提示符,你可以指定你自己的名字。<br />
BOOTCOMMAND是指定uboot起来后,自动执行的命令,这里是让uboot自动设置自己的ip和tftp服务器的ip,然后设定传递给kernel的参数,最后三个命令是把kernel镜像和initramfs镜像装载进来,并从内存指定地址开始执行指令。其实这些命令,也可以在uboot起来后,自己输入。
</p>
<p>
注意:在设置uboot的ip的时候,一定要和qemu给定的ip对应。由于这里使用的qemu内部自带的tftp服务,所以这里的ip和qemu内部tftp服务器的ip在同一个网段。
</p>
<p>
uboot配置完之后,可以通过如下命令来编译uboot:
<pre>
make versatilepb_config ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
make -j12 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
</pre>
</p>
<p>
如果没什么错误,就会生成一个u-boot镜像,然后我们就可以通过qemu来加载它:
<pre>
sudo qemu-system-arm -M versatilepb -kernel u-boot -m 256M -net nic -net user,tftp=~/armsource/tftp -sd hda.img -nographic
</pre>
</p>
<p>
命令执行后,你就可以和之前一样的内核加载,最后经过两次跳转,到我们的sd卡上的文件系统。
</p>
<h2>五、结语</h2>
<p>
到这里,我们最终完成了qemu -- &gt; uboot --&gt; kernel --&gt; initramfs --&gt; hda.img这一过程[10]。而这也是制作嵌入式系统,甚至一个桌面发行版本的基本流程。如果看完这篇文章后,还对嵌入式系统念念不忘,还是建议你买一块开发板,然后真真走一遍这个过程,毕竟这是用qemu模拟的。现在有很多open source hardware project(Arduino, Beagle Board, Cubieboard,Odroid,PandaBoard,Raspberry Pi),你可以购买他们的板子,然后移植任何自己喜欢的东西。由于是open source,你可以获取到很多资料,并且有社区支持。
</p>
<h2>REFERENCE</h2>
<ol>
<li> Download CodeSourcery: https://sourcery.mentor.com/GNUToolchain/release2449</li>
<li> toolchain: http://elinux.org/Toolchains</li>
<li> Qemu User Document: http://qemu.weilnetz.de/qemu-doc.html</li>
<li> EABI: http://en.wikipedia.org/wiki/Application_binary_interface</li>
<li> kernel debug</li>
<li> Busybox: http://www.ibm.com/developerworks/library/l-busybox/</li>
<li> FHS: http://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard</li>
<li> initrd: http://www.ibm.com/developerworks/library/l-initrd/index.html</li>
<li> Initrd/Initramfs: http://wiki.sourcemage.org/HowTo(2f)Initramfs.html</li>
<li> http://elinux.org/Virtual_Development_Board</li>
</ol>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[授权发表]利用 qemu 模拟嵌入式系统制作全过程 的相关文章

  • Ubuntu搭建开发openchannelssd的qemu的虚拟机

    1 安装带有NVMe支持的qemu QEMU Installation QEMU support for Open Channel SSDs is based on top of Keith Busch s qemu nvme branch
  • QEMU虚拟机中如何安装Virtio驱动

    在计算机虚拟化中 Virtio是一种半虚拟化解决方案 即需要对Guest OS进行一定的修改 安装相应的驱动程序 能够对虚拟机的I O性能进行大幅的提升 在QEMU KVM的环境中 Virtio的后端驱动由QEMU程序提供 不需要额外的安装
  • VirtIO实现原理——数据传输演示

    文章目录 初始化 示意图 代码分析 Guest第一次添加buffer 示意图 代码分析 Notify Host Host第一次处理buffer 示意图 代码分析 Guest第二次添加buffer Host第二次处理buffer 初始化 示意
  • qemu-virtio基本原理

    virtio是相当复杂的 网上写virtio原理解析的文章也不少 这里我想通过最简练易懂的方式来解释一下virtio的原理 一方面也完善一下自己对virtio的理解 文中含有大量个人理解 如果发现有错误的地方欢迎与我交流 virtio整体流
  • win11 使用 QEMU 配置龙芯 3A5000 虚拟环境

    01 下载资源 本实验使用资源 开源模拟器qemu 下载地址 qemu w64 setup 20230822 exe loongarch 固件下载 QEMU EFI 8 0 fd loongarch 基本镜像下载 archlinux loo
  • 从零开始制作Linux

    提到制作Linux 大家都能想到如雷贯耳 大名鼎鼎的Linux from scratch 但Linux from scratch的复杂性不是普通人能轻易掌握的 对于初学者来说 任何步骤出现不一致 会让初学者遇到挫拆 攻破LFS的信心越来越低
  • Real-time Linux

    所谓实时操作系统 Real time Opearting System 是指当外接世界或数据产生时 能够接受并以足够快的速度予以处理 其处理的结果又能在规定的时间之内来控制生产过程或对处理系统做出快速响应 调度一切可利用的资源完成实时任务
  • qemu-system-x86_64 :地址解析失败 ::1:46189:名称或服务未知

    我有以下问题 当我跑步时emulator avdname抛出以下错误 qemu system x86 64 chardev socket port 46189 host 1 nowait nodelay ipv6 id modem addr
  • 是否可以使用gdb和qemu同时调试linux用户空间程序和内核空间?

    到目前为止 使用 gdb qemu 我可以单步执行 Linux 内核源代码 是否可以同时调试用户空间程序 例如 将程序从用户空间单步执行到内核空间 这样我就可以通过发出以下命令来观察 qemu 监视器上寄存器的变化info register
  • 升级到 macOS Catalina 后 Qemu 没有响应

    将我的 Mac 升级到 Catalina 后 我无法再使用 qemu 每当我尝试启动它时 它就会挂起 当 qemu 窗口处于活动状态时 菜单栏也不会响应 跑步qemu system i386 help不过确实有效 Qemu版本 4 1 0
  • x86 PIC,QEMU 在所有 CPU 上引发中断是否正确?

    我最近不得不解决 x86 PIC 的专有操作系统问题 其中操作系统预期定时器中断仅在 CPU0 上 我启用了 IO APIC 来解决这个问题并进行了 CPU 控制 因此中断仅到达 CPU0 问题解决了 有人告诉我 我们的硬件已经损坏 无法做
  • 如何使用 QEMU 模拟混合平台?

    背景 有很多关于使用 QEMU 模拟特定架构系统 平台 的文档 例如 x86 ARM 或 RISCV 系统 第一步是配置 QEMU target list 例如 configure target list riscv32 softmmu h
  • 在 qemu 中使用 GDB 调试 Linux 内核无法命中函数或给定地址

    我试图在 qemu 环境中使用 GDB 逐步理解内核启动顺序 以下是我的设置 在一个终端中我正在运行 Qemu arm bin qemu system arm M vexpress a9 dtb arch arm boot dts vexp
  • 如何使用 GCC 生成一个最小的 BIOS hello world 引导扇区,以便在真实硬件上通过 USB 记忆棒工作?

    我已经成功地生成了一个可与 QEMU 2 0 0 Ubuntu 14 04 配合使用的最小引导扇区 code16 global start start cli mov msg si mov 0x0e ah loop lodsb or al
  • 如何使用 QEMU 的简单跟踪后端?

    这是后续this https stackoverflow com questions 37522552 qemu simple backend tracing dosent print anything comment65639854 37
  • 了解 QEMU 的好来源是什么?

    您会推荐什么书或网站来了解 QEMU 我想查看一些使用示例以及如何使用 API 最佳资源 主要 QEMU 使用文档 http wiki qemu org Manual Qemu 手册页 http manpages ubuntu com ma
  • 如何在32位Linux上运行16位代码?

    我编写了一个小型 16 位汇编程序 该程序在某些内存位置写入一些值 有没有办法可以在 Linux 上的 32 位保护模式下测试它 qemu http wiki qemu org Main Page dosbox http www dosbo
  • 如何编写 Sparc 程序集并在 Qemu 或 Simics 中运行其二进制文件?

    我正在尝试开始编写一些 Sparc 程序集 但我不知道如何汇编和运行代码 我已经用 arcTools 编写了 arc 但这就是我对汇编的了解 我已经下载了 simics 和 qemu 但我不知道从这里去哪里 有人能指出我正确的方向吗 谢谢
  • qemu kvm:如何获取性能监控中断?

    我在操作系统内核中编写了一些函数 以便在指令计数器溢出时发出性能监控中断 PMI 它在我的机器 Intel core i5 上运行良好 但是当我使用 qemu 在 qemu 上运行它时 qemu system x86 64 enable k
  • Yocto“无法运行 qemu:无法初始化 SDL(x11 不 > 可用)”

    所以我在本地构建服务器上安装了 Yocto 因为谁希望大规模构建占用他们的工作区 amirite 主机和服务器是Arch Linux 4 19 44 1 lts 无论如何 我只是从找到的快速构建页面运行示例here https www yo

随机推荐

  • Linux:CPU频率调节模式以及降频方法简介

    概述 cpufreq的核心功能 xff0c 是通过调整CPU的电压和频率 xff0c 来兼顾系统的性能和功耗 在不需要高性能时 xff0c 降低电压和频率 xff0c 以降低功耗 xff1b 在需要高性能时 xff0c 提高电压和频率 xf
  • Linux:rsyslog 日志丢失 messages lost due to rate-limiting

    系统日志显示 cat var log messages Apr 7 16 20 01 ngnodeb rsyslogd imjournal 154664 messages lost due to rate limiting 解决方法 修改配
  • Linux:shell 中的单行注释和多行注释

    关于 shell 中的单行注释和多行注释 单行注释 众所周知 xff0c 使用 比如想要注释 echo 34 Hello World 34 root 64 test vim test sh echo 34 Hello World 34 多行
  • Shell三剑客之sed:修改 xml

    修改前 vim config xml lt config input type verify 61 34 bool 34 name 61 34 flow bypass class 34 visible 61 34 true 34 gt fa
  • STM32串口通信

    STM32串口通信 一 基于寄存器与基于固件库编写的差异二 stm32串口通信实战1 烧录方式2 代码及效果图 三 C语言程序里全局变量 局部变量 堆 栈等概念四 stm32的堆 栈 全局变量的分配地址 一 基于寄存器与基于固件库编写的差异
  • keil下的FreeRtos多任务程序

    keil下的Freertos多任务程序 1 手动移植FreeRtos xff08 以STM32F103为例 xff09 2 直接使用野火的模板 1 手动移植FreeRtos xff08 以STM32F103为例 xff09 用该链接下载Fr
  • 随笔小记(二十七)

    神经网络中Epoch Iteration Batchsize相关理解和说明 batchsize xff1a 中文翻译为批大小 xff08 批尺寸 xff09 简单点说 xff0c 批量大小将决定我们一次训练的样本数目 batch size将
  • 手把手教物体检测——EfficientDet

    目录 摘要 训练数据 1 下载Pytoch版的EfficientDet 2 制作数据集 3 下载EfficientNets预训练模型 4 安装模型需要的包 5 放置数据集 6 修改train py中的参数 测试 注意 摘要 谷歌大脑团队 Q
  • 简化的围棋棋子规则(C++实现)

    题目 xff1a 输入棋盘 xff1a 1 1 2 3 2 3 3 3 2 3 3 3 2 2 2 3 3 3 1 2 2 2 3 3 2 1 1 2 3 1 其中1代表空 xff0c 2代表白子 xff0c 3代表黑子 xff09 输出
  • MATLAB中将图像转换为二值图像im2bw

    在MATLAB中将图像转换为二值图像 xff0c 主要运用im2bw函数 xff0c 涉及到一个灰度门槛的数值 对于灰度图像 bw 61 im2bw I level level空着的话 xff0c 默认是0 5 level一般使用grayt
  • Ubuntu 20.04 Gazebo安装 及模型库下载

    安装参考自官方教程noetic版本 xff0c 为了安装模型库 xff0c 就一起编辑了 1 设置你的电脑来接收软件 sudo sh c 39 echo 34 deb http packages osrfoundation org gaze
  • git pull强制覆盖本地修改

    有时本地代码做了修改 xff0c 但又想放弃这部分修改 xff0c 重新在新代码基础上进行开发 xff0c 这时可用如下方法覆盖先前修改 xff0c 并拉取远程仓更新本地代码 方法一 xff1a git fetch git reset ha
  • gazebo中视觉仿真怎么使用自定义贴图的问题

    gazebo中提供了很少的贴图 xff0c 场景只是用这几张贴图 xff0c 视觉SLAM仿真很容易在不该闭环的时候闭环 xff0c 导致根本没法用 那么我们怎么添加自己的贴图呢 xff1f 首先gazebo建模 使用默认贴图 xff0c
  • 传统定位方法简介--------里程计、IMU惯性传感器以及光电编码器等

    移动机器人最初是通过自身携带的内部传感器基于航迹推算的方法进行定位 xff0c 后来进一步发展到通过各种外部传感器对环境特征进行观测从而计算出移动机器人相对于整个环境的位姿 目前为止 xff0c 形成了基于多传感器信息融合的定位方法 现有移
  • 路由器接口

    深刻认识到如果不好好学习计算机网络 xff0c 对于自己学习后台的知识有很大的阻碍 所以 xff0c 这段时间好好把这方面的知识加强一下 一般路由器上的接口分为三大类 xff1a 一 用于局域网的LAN接口 二 用于广域网接入 互联的WAN
  • UART、I2C、SPI接口常见面试问题总结

    UART 定义 xff1a Universal Asynchronous Receiver Transmitter 通用异步收发传输器 特点 xff1a 速率不快 可全双工 结构上一般由波特率产生器 UART发送器 UART接收器组成 xf
  • ubuntu18.04配置ORB-SLAM3(包含ROS)完整版教程

    ORB SLAM3安装教程 ORB SLAM3安装准备1 C 43 43 11 or C 43 43 0x Compiler2 Pangolin 61 61 出现的问题 61 61 3 OpenCV安装4 Eigen安装5 boost安装6
  • 视觉里程计--视觉slam7.1/相机运动估计视觉算法

    视觉里程计 本篇文章记录了少许阅读 视觉slam14讲 的阅读整理 xff0c 不是特别全面 xff0c 只是为了本次项目中特定任务搜查资料 xff0c 时间比较紧 xff0c 文章并没有全面涵盖所有知识点 日后若时间有空闲 xff0c 将
  • [授权发表]源码分析:动态分析 C 程序函数调用关系

    By Falcon of TinyLab org 2015 04 15 最初发表 xff1a 泰晓科技 聚焦嵌入式 Linux xff0c 追本溯源 xff0c 见微知著 xff01 原文链接 xff1a 源码分析 xff1a 动态分析 C
  • [授权发表]利用 qemu 模拟嵌入式系统制作全过程

    利用qemu模拟嵌入式系统制作全过程 by Pingbo Wen of TinyLab org 2013 08 31 最初发表 xff1a 泰晓科技 聚焦嵌入式 Linux xff0c 追本溯源 xff0c 见微知著 xff01 原文链接