用户态Linux内核启动例子
页面
正面例子
uname -a
#Linux zz 4.15.0-29-generic #31-Ubuntu SMP Tue Jul 17 15:39:52 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
###############################
mkdir ~/uml/; cd ~/uml/;
wget http://uml.devloop.org.uk/kernels/kernel64-4.3.5.xz
xz -d kernel64-4.3.5.xz
chmod 755 kernel64-4.3.5
wget http://fs.devloop.org.uk/filesystems/BusyBox-1.13.2/BusyBox-1.13.2-amd64-root_fs.bz
bzip2 -d BusyBox-1.13.2-amd64-root_fs.bz2
ls -lh
#-rw-rw-r-- 1 z z 4.0M 2月 16 2012 BusyBox-1.13.2-amd64-root_fs
#-rwxr-xr-x 1 z z 101M 2月 1 2016 kernel64-4.3.5
./kernel64-4.3.5 ubda=./BusyBox-1.13.2-amd64-root_fs mem=128M
#用户态内核正常启动 直至出现shell命令提示符
#命令提示符下输入 halt, 该用户态内核即可关机
#以下版本的:用户态内核正常启动 直至出现shell命令提示符:
./kernel64-4.2.8 ubda=./BusyBox-1.13.2-amd64-root_fs mem=128M
./kernel64-4.1.42 ubda=./BusyBox-1.13.2-amd64-root_fs mem=128M
./kernel64-3.19.8 ubda=./BusyBox-1.13.2-amd64-root_fs mem=128M
反面例子
错误举例:高版本内核的宿主机 启动 低版本用户态内核 会失败
uname -a
#Linux mechrev 5.19.0-42-generic #43~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Apr 21 16:51:08 UTC 2 x86_64 x86_64 x86_64 GNU/Linux
./kernel64-4.3.5 ubda=./BusyBox-1.13.2-amd64-root_fs mem=128M
'Core dump limits :
soft - 0
hard - NONE
...
<6>[ 0.080000] Call Trace:
<6>[ 0.080000] [<60635aed>] ? __getgrnam_r+0xad/0x200
<6>[ 0.080000] [<60612d4d>] ? grantpt+0x20d/0x240
<6>[ 0.080000] [<6060fc0c>] ? __isatty+0xc/0x20
<6>[ 0.080000] [<60612eef>] ? __ptsname_internal+0x11f/0x290
<6>[ 0.080000] [<60612d11>] ? grantpt+0x1d1/0x240
<6>[ 0.080000]
已放弃 (核心已转储)
'
qemu+gdb调试kernel(完全不熟悉内核的情况下,试图搞清楚kernel中有哪些全局性内容和行为)
假设 环境"qemu+gdb调试kernel" 已经搭建好, 并且作者只是linux使用者,对linux kernel完全不熟悉,想要搞清楚 kernel中有哪些全局性内容和行为, 怎么做?
步骤如下:
-
宿主机禁用地址空间虚拟化
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
-
譬如要了解 kernel中是否有 进程表全局变量。 在内核代码中搜索 函数入参为 struct task_struct 指针的,gdb对该函数加断点。
-
多次运行内核,确定每次运行内核都有该同样的struct task_struct地址值出现。
是否相同 取决于 : 宿主机randomize_va_space是否禁用、qemu实现
若 无法相同,则本方案无效,不用继续了。
-
再次运行内核,gdb对该地址值范围进行watch,以找到该地址首次产生的代码处。
此时
如果发现了 内核给struct task_struct 分配内存空间的办法,则理论上该分配办法是统一的,则监控该分配方法 或许能找到更多的全局变量
如果struct task_struct 只是出现在一个写死的数组的地方,则步骤2到4只能看作是单独对进程实施的,要对内存管理再单独实施步骤2到4
延迟正常例子
// linux-5.12.14/init/main.c
int x;
asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
{
char *command_line;
char *after_dashes;
// delayNsecond(32,10);//延迟若干秒,以等待 OrbitProfiler 连接.
//下载Orbit的deb包,本地安装后, 启动Orbit: /opt/orbitprofiler/Orbit
unsigned int nSecond=1000;
unsigned int cnt1=1UL << 31;
//改用c89语法
unsigned int k;
unsigned int i;
for(k=0; k < nSecond; k++){
for(i=0; i< cnt1; i++);{
x+=k*i;
command_line=(char*)(x);
}
}
set_task_stack_end_magic(&init_task);
smp_setup_processor_id();
debug_objects_early_init();
//...
以下是 快速学习linux内核 路径
1. 用户态Linux简介: 多进程实现 和 多线程实现
多进程实现: skas3+UML
宿主机kernel 中含有 skas3, 客户kernel中含有UML
跟踪工具 OrbitProfiler 难以跟踪 多进程, 实际上 多进程本身就难以跟踪。
这是目前主流linux kernel中的样子,但此情况难以快速学习,放弃
多线程实现: (无skas或skas2)+UML
宿主机kernel 中含有 skas2 或 不含skas, 客户kernel中含有UML
这只是理论,实际 只有 低版本(2.5,2.6)内核 能禁用 skas3, 具体看"2.结论" 。
多线程 更容易被 跟踪工具C++ Profiling 跟踪.
参考
多线程实现用户态Linux 环境搭建 讨论:这里只是讨论,可行路径请看"2.结论"
-
低版本kernel 的宿主机A, 低于 2.6.0 ,比如2.5.0
-
低版本kernel 的客户UML, 比如 2.4.0(和宿主机kernel版本一致也许方便些,这里为了书写不混淆才选不一致)
-
可能需要在另一个较高版本机器B,比如CentOS5 i386, 在其上 编译出 2.4.0 UML
-
OrbitProfiler 运行于linux上最早是2018年,且只有.deb包。 显然不可能运行在如此低版本kernel上。 更早2008年的OrbitProfiler是ms windows下的c++代码。
-
如此低版kernel 估计OrbitProfiler难以编译.
-
高版本内核 如果能禁用SKAS3呢? 高版本难以禁用SKAS3?
MODE_SKAS 最高只在2.6.23内核上
This option controls whether skas (separate kernel address space) support is compiled in. Unless you have specific needs to use TT mode (which applies almost only to developers), you should say Y here. SKAS mode will make use of the SKAS3 patch if it is applied on the host (and your UML will run in SKAS3 mode), but if no SKAS patch is applied on the host it will run in SKAS0 mode, which is anyway faster than TT mode.
MODE_TT 最高只在2.6.23内核上
archLinux有低于2.6内核的iso,但GUI难搞,转向Fedora1
年 | archLinux版本 | 内核版本 | — |
---|---|---|---|
2004-03-01 | 0.6 | 2.6.3 | No |
2003-07-21 | 0.5 | 2.4.21 | No |
2002-12-18 | 0.4 | 2.4.20 | No |
2002-08-07 | 0.3 | 2.4.19 | No |
2002-04-17 | 0.2 | 2.4.18 | No |
2002-03-12 | 0.1 | 2.4.18 | No |
Fedora 1 使用 kernel 2.4.22
年 | Fedora 版本 | 内核版本 | GNOME |
---|---|---|---|
2003-11-06 | 1 (Yarrow) | 2.4.22 | 2.4 |
ubuntu 最低发行版04.10 所用kernel 2.6.8 ,不符合要求
2. 结论
快速学会Linux内核结论 : 观察 多线程实现用户态Linux内核 的唯一可能途径
1. 宿主机 内核只能是 以下两行之一:
启用/禁用选项 | 选项 | 内核版本范围 |
---|---|---|
禁用 | CONFIG_MODE_SKAS | 2.5.60–2.5.75, 2.6.0–2.6.23 |
启用 | CONFIG_MODE_TT | 2.6.19–2.6.23 |
此表格意思是:
- 使用内核版本范围2.5.60–2.5.75, 2.6.0–2.6.23 以禁用CONFIG_MODE_SKAS;
- 或 使用内核版本范围2.6.19–2.6.23 以启动 CONFIG_MODE_TT
2. 客户UM内核 版本 满足:
- 一、 客户UM内核 与 宿主机内核 版本 相近 ,
如果 宿主与客户 版本差异太大, 宿主 如何 模拟或响应 客户?
- 二、且 客户UM内核 为2.6.x 以使用ARCH=um
2.5及更低版本,无法使用ARCH=um ,
但估计没有ARCH=um,也能编译出UM内核,比如估计对2.4.32应用UM页面中的uml-2.4.32-bs2 patch能编译出UM内核,但这样更难了。
ARCH=um 大概意思 是 使用 此目录 “linux内核源码/arch/” 的 um目录,2.5及更低版本 的 arch目录下 没有 um目录。
3. 宿主机发行版选择:
distribution | distribution版本 | distribution代号 | kernel版本 | distribution年份 |
---|---|---|---|---|
RHEL | 5.x | 2.6.18 | ||
----- | ----- | ----- | ----- | ----- |
archlinux | 0.6 | 2.6.3 | ||
archlinux | 0.7 | 2.6.10 | ||
archlinux | 0.7.1 | 2.6.15 | ||
archlinux | 0.7.2 | 2.6.16.16 | ||
archlinux | 0.8 | 2.6.20.4 | ||
archlinux | 2007.05 | 2.6.21.1 | ||
archlinux | 2007.05-Linuxtag2007 | 2.6.21.3 | ||
archlinux | 2007.08 | 2.6.22.1 | ||
archlinux | 2007.08.1 | 2.6.22.6 | ||
archlinux | 2007.08-2 | 2.6.22.9 | ||
----- | ----- | ----- | ----- | ----- |
Fedora | 3 | (Heidelberg) | 2.6.9~2.8 | 2004-11-08 |
Fedora | 4 | (Stentz) | 2.6.11~2.10 | 2005-06-13 |
Fedora | 5 | (Bordeaux) | 2.6.15~2.14 | 2006-03-20 |
Fedora | 6 | (Zod) | 2.6.18~2.16 | 2006-10-24 |
Fedora | 7 | (Moonshine) | 2.6.21~2.18 | 2007-05-31 |
Fedora | 8 | (Werewolf) | 2.6.23~2.20 | 2007-11-08 |
----- | ----- | ----- | ----- | ----- |
Ubuntu | 04.10 | Warty Warthog | 2.6.8 | xxx |
Ubuntu | 05.04 | Hoary Hedgehog | 2.6.10 | |
Ubuntu | 05.10 | Breezy Badger | 2.6.12 | |
Ubuntu | 06.06 | Dapper Drake | 2.6.15 | |
Ubuntu | 06.10 | Edgy Eft | 2.6.17 | |
Ubuntu | 07.04 | Feisty Fawn | 2.6.20 | |
Ubuntu | 07.10 | Gutsy Gibbon | 2.6.22 | |
----- | ----- | ----- | ----- | ----- |
Debian | 3.1 | Sarge | 2.4.27, 2.6.8 | 6 June 2005 |
Debian | 4.0 | Etch | 2.6.18, 2.6.24 | 8 April 2007 |
Debian | 5.0 | Lenny | 2.6.26 | 14 February 2009 |
4. 选择版本以作配合:
- A. 安装3中的发行版到 “virtualBox或vmware或真机” ,以作为宿主机,
这些发行版基本都只能在 32位cpu即i386模式下运行。
- B. 在宿主机中 以ARCH=um 编译 2中选择的内核版本 作为 客户UM内核,
注意此时使用了宿主机,所以不要在此之前做步骤C,那样宿主机更容易崩溃。
- B2. 若E中的C++ Profiling 是需要从源码编译的,在此时进行。
注意此时使用了宿主机,所以不要在此之前做步骤C,那样宿主机更容易崩溃。
- C. 在宿主机中 按1中表格两行之一的配置 编译 1中的内核版本 并 替换 此 宿主机 中的内核,
所以新编宿主与原宿主这两者版本至少相近 最好相等 否则替换后 肯定宿主机崩溃,
简单点 要求新宿主与原宿主版本相等。
- D. 客户UM内核 在 宿主机 中作为普通应用运行,
检查 此时 客户UM内核 是不是以 单一进程 在运行?
- 情况1:若是 即获得 单进程中的多线程样子的UM内核 则 继续步骤E
- 情况2:若不是 即 客户UM内核 依然是多进程模式,
- 步骤A中重选发行版,
- 步骤B中的2中重选UM版本,
- 步骤C中的1中的表格重选另一行 ,
- 重做步骤A到步骤D,
- 直到 步骤D能 到 “情况1”,
- 或尝试完所有可能步骤D也到不了"情况1",即 本任务失败,要么 本任务理论上有问题导致不可能成功 要么 失败原因是还不了解的其他问题导致的。
- E. 使用C++ Profiling工具 监控 单进程的 客户UM内核
理论上,该单进程中应该有大量模拟操作系统各部件的线程们,此时应该能更清晰的、更容易的学习到Linux内核的深度内容。
C++ Profiling工具列表, 未列出OrbitProfiler