.. Kenneth Lee 版权所有 2021
:Authors: Kenneth Lee :Version: 1.0 :Date: 2021-11-26 :Status: Draft
5.14
2021年8月29日发布。\ [1]_
Idea很简单,就是用这个fd后面的back memory不和其他进程共享,都是这个进程独占,包 括root进程都不能用。
实现在mm/secretmm.c中,我的感觉就是实现了一个内存文件,可能会拒绝其他进程用它分 配的backend页,其他什么都看不到,我理解不了这个需求。
阿里巴巴提交的特性,增加CFS的cgroup控制参数允许冲击性的流量(这是解决双十一问题 吗?),参数是使能后,group中的进程,前一个周期没有用完的runtime可以加到下一个 周期上。补丁提供的数据显示在schbench上起到很好的整形效果,避免了最坏情况的进程的 时延百倍的增加。
参数cpu.cfs_burst_us用于控制积累的上限,默认是0,表示不积累。而 cpu.cfs_period_us表示周期内的quota。
算法类问题的原理我就不再这里分析了,参数一变什么都会变。
一组新的prcl参数,用于控制进程是否和其他进程共享同一个核的超线程,把安全要求高 的进程隔离出来,避免被侧信道攻击。
有四个prctl命令,包括:
create针对一个pid创建一个cookie,get把它取出来,share把它共享给其他pid。说起功 能很简单,就看你需不需要了。Linus说它:
make little sense to most people.
这个特性本身不小,还包含19个独立补丁(包括文档更新)。
madvise增加两个针对页表prefault的新命令:
这应该是个细节的需求,据说是qemu性能优化用到的。光这么一想,我是没有想到什么时 候页表prefault会成为瓶颈的。
这个版本有几个kunit的补丁,我一直没有认真看过这个子系统的思路,这次来看看:
首先,这不是一个代码逻辑级别的单元测试框架,而是基于一个运行起来的Linux上的单元 测试框架。这个运行可以基于um(这确实是个好思路,不用我这么辛苦插那么多桩,但不插桩 测试范围可能有限了,估计只能测试系统库),也可以基于qemu。
要验证一下用法很简单,随便找一个源代码运行命令就行:::
kenny@lklp02:~/work/linux-kernel-dev$ ./tools/testing/kunit/kunit.py run [09:09:58] Configuring KUnit Kernel ... Generating .config ... Populating config with: $ make ARCH=um olddefconfig O=.kunit [09:10:00] Building KUnit Kernel ... Populating config with: $ make ARCH=um olddefconfig O=.kunit Building with: $ make ARCH=um --jobs=8 O=.kunit ../arch/x86/um/Makefile:44: FORCE prerequisite is missing
[09:10:35] Starting KUnit Kernel (1/1)... [09:10:35] ============================================================ [09:10:36] =============== time_test_cases (1 subtest) ================ [09:10:36] [PASSED] time64_to_tm_test_date_range [09:10:36] ================= [PASSED] time_test_cases ================= [09:10:36] ================ sysctl_test (10 subtests) ================= [09:10:36] [PASSED] sysctl_test_api_dointvec_null_tbl_data [09:10:36] [PASSED] sysctl_test_api_dointvec_table_maxlen_unset [09:10:36] [PASSED] sysctl_test_api_dointvec_table_len_is_zero [09:10:36] [PASSED] sysctl_test_api_dointvec_table_read_but_position_set [09:10:36] [PASSED] sysctl_test_dointvec_read_happy_single_positive [09:10:36] [PASSED] sysctl_test_dointvec_read_happy_single_negative [09:10:36] [PASSED] sysctl_test_dointvec_write_happy_single_positive [09:10:36] [PASSED] sysctl_test_dointvec_write_happy_single_negative [09:10:36] [PASSED] sysctl_test_api_dointvec_write_single_less_int_min [09:10:36] [PASSED] sysctl_test_api_dointvec_write_single_greater_int_max [09:10:36] =================== [PASSED] sysctl_test =================== ... [09:10:36] Testing complete. Passed: 88, Failed: 0, Crashed: 0, Skipped: 2, Errors: 0 [09:10:36] Elapsed time: 38.381s total, 2.087s configuring, 34.866s building, 1.381s running
原理也很容易猜到,就是编译了一个um linux,只能在命令行运行就是了。如果是qemu的 版本,估计就是运行起一个虚拟机,然后通过debugfs接口要求内核调用对应的测试函数( 通过kunit_test_suite宏定义),然后在内核中直接调用那个函数。这样基本上你不能插 桩,但你可以直接用Linux内已经存在的任何facility,如果你写的是一个库,比如写了一 个list,你要测试这个list,这种方法就很方便,但如果你做了一个驱动,想测试这个驱 动的一个组合逻辑,这种方法就没戏了。
框架提供最基本的facility,除了刚才提到的定义kunit_test_suite用于暴露测试用例接 口,还有check(), compare()这些函数用于检查结果。
说起来,这个东西简单得很,使用范围也有限,就这么着吧。
比较有趣的是它的报告格式,叫TAP,(Test Anything Protocol),是个简单得要死的文 本格式,我是没想到连这种东西都可以标准化(我不是讽刺,实际上这样简单的标准化也 是有用的)。
对了,这个框架是Google做的。
kunit的分析让我突然对UML有了兴趣。我原来对它没有兴趣主要是我觉得它不是“真的”, 用qemu来运行一个Linux,Linux在qemu里面是“真的”,有特权级,有多CPU,但UML运行在 用户态,这些东西肯定都是模拟出来的,它还受用户态权限的各种限制,我就觉得既然 qemu能用,就没有必要用UML。
但kunit给了我一个启示:如果我仅仅要测试一个内核的函数,UML是有明显优势的,因为 它可以直接在一个用户空间里面运行,我不用老想着怎么在qemu和kenrel两头插桩。
所以我简单分析一下UML的边界,也就是前面提到的问题,UML具体是如何模拟的。
先大概看一下UML的运行模型,这个方案这样使用:::
make ARCH=um O=my_um_test cd my_um_test ./linux ubd0=rootfs.img root=/dev/ubda init=/bash/sh
除了不需要虚拟机(自己就是虚拟机),其他各方面和qemu等虚拟机的用法很接近,说明 它也是一种模拟方案,而且还直接可以解释一个文件系统。它也不需要root工作权限。从 这点看,它就是用普通的用户服务提供一个虚拟的系统的。
arch代码在arch/um目录中,由于是个用户程序,就有main入口了。这个入口在 arch/um/os-Linux/main.c,。除了准备工作,主函数应该是start_uml(),这里创建了CPU 模拟线程:start_kernel_proc(),这里就会调用内核真正的入口start_kernel(),里面就 是标准的Linux启动行为,对应的平台相关调用就用uml的实现代替。用gdb跟踪这个过程可 以看到这些实现包括:
这是根据快速看代码形成的印象,可能理解有错。另外,根据这里的描述:
http://user-mode-linux.sourceforge.net/old/skas.html
过去UML是通过每个Guest进程对应一个Host进程来实现的,靠一个独立线程跟踪踩空的系 统调用,调度到UML自己的内核中(所以后来这个方案称为TT模式,Tracing Thread),而 且和内核共享空间,所以安全性不好,性能也低,现在的实现称为skas(Separate Kernel Address Space),这需要在Host Kernel上增加ptrace接口。这个文档很旧了,只能说明 历史,但跟踪当前的实现,确实看到这个异常的处理流程是这样的:::
regs=regs@entry=0x0) at ../mm/memory.c:4758
is_write=is_write@entry=0, is_user=is_user@entry=1, code_out=code_out@entry=0x62803e34)
at ../arch/um/kernel/trap.c:74
at ../arch/um/kernel/trap.c:226
at ../arch/um/kernel/trap.c:190
at ../arch/um/os-Linux/skas/process.c:482
这确实靠ptrace实现,说明这些支持已经在主线内核中了。这要分析下去就复杂了,我到 此为止吧,我觉得这个功能就让它暂时停留在kunit这样的功能上吧。