用户态Linux内核: 多线程实现

用户态Linux内核启动例子

页面

kernels

root_fs

正面例子


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中有哪些全局性内容和行为, 怎么做?

步骤如下:

  1. 宿主机禁用地址空间虚拟化 echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

  2. 譬如要了解 kernel中是否有 进程表全局变量。 在内核代码中搜索 函数入参为 struct task_struct 指针的,gdb对该函数加断点。

  3. 多次运行内核,确定每次运行内核都有该同样的struct task_struct地址值出现。

    是否相同 取决于 : 宿主机randomize_va_space是否禁用、qemu实现

    若 无法相同,则本方案无效,不用继续了。

  4. 再次运行内核,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 跟踪.

参考

  1. old/skas
  2. old/diary

多线程实现用户态Linux 环境搭建 讨论:这里只是讨论,可行路径请看"2.结论"

  1. 低版本kernel 的宿主机A, 低于 2.6.0 ,比如2.5.0

  2. 低版本kernel 的客户UML, 比如 2.4.0(和宿主机kernel版本一致也许方便些,这里为了书写不混淆才选不一致)

  3. 可能需要在另一个较高版本机器B,比如CentOS5 i386, 在其上 编译出 2.4.0 UML

  4. OrbitProfiler 运行于linux上最早是2018年,且只有.deb包。 显然不可能运行在如此低版本kernel上。 更早2008年的OrbitProfiler是ms windows下的c++代码。

  5. 如此低版kernel 估计OrbitProfiler难以编译.

  6. 高版本内核 如果能禁用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版本对应kernel版本

archLinux版本内核版本
2004-03-010.62.6.3No
2003-07-210.52.4.21No
2002-12-180.42.4.20No
2002-08-070.32.4.19No
2002-04-170.22.4.18No
2002-03-120.12.4.18No

archLinux低版本iso下载

Fedora 1 使用 kernel 2.4.22

Fedora版本对应kernel版本

Fedora 版本内核版本GNOME
2003-11-061 (Yarrow)2.4.222.4

ubuntu 最低发行版04.10 所用kernel 2.6.8 ,不符合要求

ubuntu版本对应kernel版本

2. 结论

快速学会Linux内核结论 : 观察 多线程实现用户态Linux内核 的唯一可能途径

1. 宿主机 内核只能是 以下两行之一:

启用/禁用选项选项内核版本范围
禁用CONFIG_MODE_SKAS2.5.60–2.5.75, 2.6.0–2.6.23
启用CONFIG_MODE_TT2.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. 宿主机发行版选择:

distributiondistribution版本distribution代号kernel版本distribution年份
RHEL5.x2.6.18
-------------------------
archlinux0.62.6.3
archlinux0.72.6.10
archlinux0.7.12.6.15
archlinux0.7.22.6.16.16
archlinux0.82.6.20.4
archlinux2007.052.6.21.1
archlinux2007.05-Linuxtag20072.6.21.3
archlinux2007.082.6.22.1
archlinux2007.08.12.6.22.6
archlinux2007.08-22.6.22.9
-------------------------
Fedora3(Heidelberg)2.6.9~2.82004-11-08
Fedora4(Stentz)2.6.11~2.102005-06-13
Fedora5(Bordeaux)2.6.15~2.142006-03-20
Fedora6(Zod)2.6.18~2.162006-10-24
Fedora7(Moonshine)2.6.21~2.182007-05-31
Fedora8(Werewolf)2.6.23~2.202007-11-08
-------------------------
Ubuntu04.10Warty Warthog2.6.8xxx
Ubuntu05.04Hoary Hedgehog2.6.10
Ubuntu05.10Breezy Badger2.6.12
Ubuntu06.06Dapper Drake2.6.15
Ubuntu06.10Edgy Eft2.6.17
Ubuntu07.04Feisty Fawn2.6.20
Ubuntu07.10Gutsy Gibbon2.6.22
-------------------------
Debian3.1Sarge2.4.27, 2.6.86 June 2005
Debian4.0Etch2.6.18, 2.6.248 April 2007
Debian5.0Lenny2.6.2614 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ziix

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值