1. cpu负载_内核加载_内核编译
1.1 cpu负载
- iostat 查看cpu利用率
root@mouse:~# iostat
Linux 5.4.0-92-generic (mouse) 03/17/2022 _x86_64_ (1 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
1.12 0.00 0.86 0.02 0.00 98.01
这里系统认为在默认采样周期內有 1.12 %的时间工作在用户空间,0.86 %的时间用在系统空间,总体上有98.01%的时间是空闲的。
收集是不可靠的 每当时间中断触发时,内核查看此刻运行的进程类型,并增加与此类型/状态进程对应的计数器的值。这种方法的问题是在两次时间中断之间系统(进程)能够在多种状态之间切换多次,而计数器只增加最后一种状态下的计数。
- 查看cpu 拓扑
root@mouse:~# ls /sys/devices/system/cpu/cpu0/topology/
core_cpus core_siblings_list package_cpus thread_siblings_list
core_cpus_list die_cpus package_cpus_list
core_id die_cpus_list physical_package_id
core_siblings die_id thread_siblings
- cpu拓扑信息
root@mouse:~# ls /sys/devices/system/cpu
cpu0 hotplug modalias possible smt
cpufreq isolated offline power uevent
cpuidle kernel_max online present vulnerabilities
1.2 内核加载
- 查看依赖库的方法
root@mouse:~/tool# readelf -d samllhog | grep NEEDED
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
- 断点函数 run_init_process
│ 1322 static int run_init_process(const char *init_filename) │
│ 1323 { │
│ 1324 const char *const *p; │
│ 1325 │
│B+>1326 argv_init[0] = init_filename; │
│ 1327 pr_info(“Run %s as init process\n”, init_filename); │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
remote Thread 1.1 In: run_init_process L1326 PC: 0xffffffff81000f88
(gdb)
[ 2.423743] Freeing unused kernel image (initmem) memory: 1176K
[ 2.424328] Write protecting the kernel read-only data: 20480k
[ 2.426721] Freeing unused kernel image (text/rodata gap) memory: 2040K
[ 2.427545] Freeing unused kernel image (rodata/data gap) memory: 660K
思考中…
3. 内核初始化函数 http://events.jianshu.io/p/d9ae91281850 从6小点看起
6. 内核初试化
6.1 preserve_boot_args
把引导程序传递的4个参数保存在全局数组boot_args中。
6.2 el2_setup
设定内核运行的异常等级
(1)当进入内核时,异常等级为1,那么在异常级别1执行内核。
(2)当进入内核时,异常等级为2,支持VHE那么内核继续在2执行,如果不支持那么降到1执行内核。
在虚拟化中,运行虚拟机的操作系统称为host OS,在虚拟机里面的操作系统称为guest OS,guest OS的用户进程在异常0运行,内核在异常级别1运行;kvm的特点就是直接在处理器上执行guest OS。
以虚拟机KVM为例,普通的虚拟化异常等级切换,kvm模块需要穿越异常等级1和2;Arm64引入虚拟化宿主扩展后,在异常级别2执行host OS操作系统内核,kvm就不再需要从异常级别1切换到异常级别2。
6.3 __create_page_tables
(1)创建恒等映射,恒等映射的特点就是虚拟地址和物理地址相同,为了在开启处理器的内存管理单元的一瞬间能够平滑过渡。由__enable_mmu负责开启内存管理单元,内核把函数__enable_mmu附近的代码放在恒等映射代码节(.idmap.text)中,恒等映射代码节的起始地址存放在全局变量__idmap_text_start中,结束地址存放在全局变量__idmap_text_end中。idmap_pg_dir为恒等映射的页全局目录的地址地址。
(2)在内核的页表中为内核镜像创建映射,内核镜像起始地址为_text,结束地址为_end。
6.4 __primary_switch
(1)调用函数__enable_mmu以开启内存管理单元。
(2)调用__primary_switched,设置不同异常级别的栈指针,VBAR_EL1设置为异常向量表的起始地址,计算内核镜像起始虚拟地址和物理地址的差值,保存到全局变量kimage_voffset中,调用start_kernel。
6.5 start_kernel
首先初始化基础设施,即初始化内核的各个子系统,然后调用rest_init创建init和kthreadd线程。
之后,init进程继续执行初始化,主要为smp作初始化和准备,启动所有从处理器,执行几倍0~7的初始化,挂载根文件系统,释放初始化代码和数据占用的内存,最后从文件系统中装载init程序,并转换成用户空间的init进程。
2. 总结
- 查看cpu载荷
- 理解linux内核加载
进入linux大门可以看哈这个视屏:https://ke.qq.com/course/417774?flowToken=1042383
学习还是得靠自己。❤️
2.1 技术参考
参考链接1:https://blog.csdn.net/new_abc/article/details/12942525
参考链接2:https://blog.csdn.net/jk110333/article/details/18443453
参考链接3:http://www.360doc.com/content/12/0825/22/8093902_232349882.shtml
参考链接4:http://events.jianshu.io/p/d9ae91281850