目录
在上一篇文章中,我们展示了通过QEMU仿真软件来运行Linux内核的过程。因为是仿真,所以我们可以构建不同架构平台的环境来进行调试,这对开发者学习内核非常友好。当然,为了简化过程且能够有一定代表性,平台选择了ARM。
学内核之一:基于QEMU搭建Linux内核启动调试环境_龙城赤子的博客-CSDN博客
显然,基于上文的环境,我们只能调试内核的启动过程。这是因为没有提供根文件系统,内核启动后,加载文件系统时就会异常停止,自然也无法执行shell等待用户输入。当我们想要调试一些运行过程中的内容时,就很不方便了,甚至是无法进行。比如,想看看一些系统调用的执行过程,或者设定一些触发条件,在事件产生时查看内核的处理逻辑等。
这这一篇文章中,我们就来补充缺失的根文件系统。这也算是对上一篇最后部分提出的第一个问题的解答。
在正式开始之前,对另外两个问题也做个简单的说明。
关于append参数,就是提供给内核的启动命令,效果类似uboot中传递给内核的cmdline。当然,有没有这个参数以及参数内容设置正确与否,都不影响启动过程。因为只有运行到使用参数的地方时,代码逻辑才会检测出问题。在本文中,这个参数不仅要有,而且还要正确,因为我们要加载根文件系统,让系统在模拟环境下完整运转起来。
关于GDB调试,其实我们可以将内核生成的vmlinux也看做是一个程序,那就好理解多了。vmlinux跟普通程序的区别是它的地址空间是确定下来了的。里面使用的地址也是加载后实际的地址。vmlinux.o文件则类似应用程序,使用的是相对地址。对于应用程序,可以由操作系统的加载过程完成地址的映射处理,而对于内核,就需要自己解决。
其次,GDB使用vmlinux可以明确调试过程中的符号信息。
好了,进入正题。
为了不让内核运行后挂起来,我们需要完成根文件系统的加载。这样,就需要提供一个根文件系统。对于嵌入式领域开发者来讲,busybox是流行选择。
从busybox官方网站下载一个稳定版。BusyBox
我这里下载了1.33.2版本。解压后,就可以考虑编译了。参照网上的资料,选择静态库方式。
make defconfig
make menuconfig
make CROSS_COMPILE=arm-none-eabi- ARCH=arm -j4
在menuconfig中选择静态方式 Build static binary

不过,在编译过程中出现了错误:
CC applets/applets.o
In file included from include/libbb.h:13,
from include/busybox.h:8,
from applets/applets.c:9:
include/platform.h:168:11: fatal error: byteswap.h: No such file or directory
168 | # include <byteswap.h>
| ^~~~~~~~~~~~
compilation terminated.
scripts/Makefile.build:197: recipe for target 'applets/applets.o' failed
make[1]: *** [applets/applets.o] Error 1
提示找不到byteswap.h头文件。在编译工具链目录下搜索了一下,确实没有上述头文件。具体是编译工具链自身问题还是跟busybox版本匹配问题,有时间了再研究。参考本人方法的读者,需要在这块注意了。
我选择了另一个工具链,这个是瑞星微开发板带的工具链,有上述头文件
./arm-buildroot-linux-gnueabihf/sysroot/usr/include/bits/byteswap.h
./arm-buildroot-linux-gnueabihf/sysroot/usr/include/byteswap.h
使用这个工具链,可以编译通过。所以,如果你也遇到了上述问题,可以考虑换个工具链。为确保工具链匹配,在编译之前,可以先检查一下是否包含上述头文件。另外需要注意的是,不同工具链的二进制兼容性也是要考虑的。像eabi、thumb、浮点支持情况等。这里也先留作一个问题,后续我们通过一篇新的文章来介绍于ARM相关的此类常见问题。
最终的编译工具链就换成了下面这个
make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm -j4
编译完成后,直接make install可能会有问题,尽量带上工具链,确保万无一失
make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm install
完成后,会生成一个_install目录,里面包含了基础的命令。因为是静态方式,所以不包含库。

其实,生成的各种命令是符号链接,这样不仅可以缩小体积,还可以加速启动和执行过程。内核启动加速技术就有这相关的。感兴趣的读者可以搜索相关资料研究。

目前只是具备了启动程序和周边命令。我们还要补充文件系统相关的其他目录,包括dev、etc、proc、sys等。这里面有些是内核自动生成的,有些是手动或者执行特定命令创建的。本人没有花费太多时间,参考了网上例子。具体读者可以自己搜索,这部分问题不大。
然后将生成的文件系统目录下的所有文件打包
root@ubuntu:/home/work/KernelStudy/rootfs# find . | cpio -o --format=newc > rootfs.img
cpio: File ./rootfs.img grew, 1918976 new bytes not copied
7563 blocks
现在我们有了根文件系统,剩下只需做两件事,在内核配置中指定上述文件所在目录,其次在qemu命令行中指定上述文件所在位置。我们一件一件来搞定。
这里需要注意,如果直接在内核目录下menuconfig,并在其中配置上述配置项CONFIG_INITRAMFS_SOURCE="/home/work/KernelStudy/rootfs"
则编译内核时,会引出很多配置要求

如果你一路默认选择下来,并使用前一篇文章中指定的qemu命令启动新生成的内核时,将看不到任何输出。本人试了好几次,都是这样。每次make defconfig后直接编译的版本是可用的。为了规避这个问题(后续有时间再研究),我采用了另外一种迂回的办法,就是先make defconfig,然后打开生成的.config文件,直接修改里面的CONFIG_INITRAMFS_SOURCE项目,之后执行make bzImage -j4 ARCH=arm CROSS_COMPILE=arm-none-eabi-。此时虽然还会出现一些配置项,但是默认处理后,编译的内核是可以通过qemu启动的。

现在,我们在qemu命令中指定append附带的cmdline以及关联的根文件系统img文件。
qemu-system-arm -nographic -m 512M -M virt -kernel /home/work/KernelStudy/Kernel/linux-4.19.244/arch/arm/boot/zImage -append "rdinit=/linuxrc root=/dev/ram console=ttyAMA0 loglevel=8" -initrd /home/work/KernelStudy/rootfs/rootfs.img
之后,内核启动起来。且cmdline也传递进去了

最后,成功加载根文件系统

我们看到,命令可以使用
在此基础上,我们就可以调试运行状态的内核了。关于GDB调试内核过程及前面提到的问题,我们下一篇再讲。今天就到这里。
JUST DO IT
ENJOY IT
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/
GivenIamadumbprogrammerandIamusingrspecandIamusingsporkandIwanttodebug...mmm...let'ssaaay,aspecforPhone.那么,我应该把“require'ruby-debug'”行放在哪里,以便在phone_spec.rb的特定点停止处理?(我所要求的只是一个大而粗的箭头,即使是一个有挑战性的程序员也能看到:-3)我已经尝试了很多位置,除非我没有正确测试它们,否则会发生一些奇怪的事情:在spec_helper.rb中的以下位置:require'rubygems'require'spork'
我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain
是否有可能:before_filter:authenticate_user!||:authenticate_admin! 最佳答案 before_filter:do_authenticationdefdo_authenticationauthenticate_user!||authenticate_admin!end 关于ruby-on-rails-before_filter运行多个方法,我们在StackOverflow上找到一个类似的问题: https://
使用Ruby1.9.2运行IDE提示说需要gemruby-debug-base19x并提供安装它。但是,在尝试安装它时会显示消息Failedtoinstallgems.Followinggemswerenotinstalled:C:/ProgramFiles(x86)/JetBrains/RubyMine3.2.4/rb/gems/ruby-debug-base19x-0.11.30.pre2.gem:Errorinstallingruby-debug-base19x-0.11.30.pre2.gem:The'linecache19'nativegemrequiresinstall
我有:When/^(?:|I)follow"([^"]*)"(?:within"([^"]*)")?$/do|link,selector|with_scope(selector)doclick_link(link)endend我打电话的地方:Background:GivenIamanexistingadminuserWhenIfollow"CLIENTS"我的HTML是这样的:CLIENTS我一直收到这个错误:.F-.F--U-----U(::)failedsteps(::)nolinkwithtitle,idortext'CLIENTS'found(Capybara::Element