硬件环境
硬件资料
核心移植
驱动移植
- linux-5.11 ok6410a 增加 网卡 支持
- linux-5.11 ok6410a 增加 lcd 支持
- linux-5.11 ok6410a 增加 usb 支持
- linux-5.11 ok6410a 增加 usb camera支持 及 测试demo
rootfs及其他用户空间工具的制作
分析
静态分析
Makefile Kconfig Kbuild 分析
简易开发环境搭建
汇编启动分析
- linux-5.11运行过程简略分析
- 从 u-boot 的 theKernel 到 linux的 start_kernel 详细过程解析
- start_kernel函数用的栈 及 arm调用堆栈实验分析-TODO
start_kernel 启动分析
- start_kernel 运行时的关注点
1.打印
2.内存
3.硬件初始化(设备)
4.进程建立及调度
4.1 进程的创建(idle及其他)
4.2 多进程的调度
4.3 进程通信机制
4.4 线程同步机制
5.异常向量表角度
5.1 中断
5.2 其他异常
A.其他
1. 网络
2. 文件系统
以打印角度分析 启动
- 从打印角度简略分析第一阶段,共2阶段
- 第一阶段之setup_arch
- 第一阶段之mem
- 第一阶段之irq
- 第一阶段之console 待完善
- 第一阶段之vfs 待完善
- 从打印角度简略分析第二阶段,共2阶段 待完善
- 第二阶段之do_initcalls 待完善
- 第二阶段之initrd/initramfs技术 参考这个 TODO
以功能角度分析 启动
- 从功能角度简略分析总览,共三阶段 待完善
- 从功能角度简略分析第一阶段,共三阶段
- 从功能角度简略分析第二阶段,共三阶段
- 第二阶段之idle进程
- 从功能角度简略分析第三阶段,共三阶段
- 第三阶段之init进程
- 第三阶段之kthreadd进程
以进程角度分析 启动
一开始 是 裸机程序
然后将裸机程序 封装成 idle 进程
然后idle 就开始 fork 出 kernel_init 和 kthreadd
然后调度 开始,混乱的多进程调度开始了
接着 kthreadd fork出了 所有的内核进程
接着 用户进程init及其子进程 fork出了 所有的用户进程
计算机三大抽象之一
进程对CPU虚拟化 // 进程是对处理器 主存 和IO设备的抽象表示
考虑进程执行的时候(除去考虑竞态)一般不考虑调度
因为对于该进程来说,它执行的时候占用了整个cpu
- 裸机和进程的区别
- 进程的发展历史
- idle进程的建立过程
- linux TCB 的分析
- fork的分析
- 不同进程之间的区别 内核进程/内核线程/用户进程/用户线程
- 进程相关的寄存器-sp与pc
- 主要内核线程解析
- [调度的需求及历史及整体分析]
为什么需要调度
因为多进程的需求
为什么需要多进程
因为 只有一个进程,造成资源浪费
虽然有调度,可指令还是 one by one 执行的
宏观并行,微观串行
调度的实质
选中一个进程 (调度的核心,如何发展的?)
保存当前的进程/恢复选中的进程(架构强相关,因为涉及到寄存器的保存和恢复)
进程创建/调度的性能参数
???
系统有多少进程?进程是怎么被看见的?
如何遍历进程
以内存角度分析 启动
内存管理的历史
内存管理的性能
-
内存管理第三阶段及buddy的alloc和free . . .及 buddy的消费者
-
内存管理第四阶段及slab的alloc和free. . . . .及 slab的消费者
- 用户虚拟内存管理 VMA & [VMA与vmalloc的区别]
1.vmalloc ,一个内存块用vm_area 表示,挂载到了 vmap_area_root 和 vmap_area_list
vm_struct 结构体是其他模块可见的,vmap_area是动态映射区内部使用的
全局变量vmap_area_root是红黑树的根节点
全局变量vmap_area_list用于将vmap_area按地址从小到大排序。
2. mmap 一个内存块用vm_area_struct 表示,挂载到了 进程PCB中的mm_struct中的 mm_rb 和 mmap
- 基于VMA 的 sys_mmap 和 sys_brk
- glibc提供的mmap与malloc
- mmap实例 以fb为参考 从应用到驱动
- glibc提供的mmap的四种用途
- glibc提供的mmap四种用途参数及扩展
- glibc提供的mmap的四种用途之一 共享匿名映射 与 共享文件映射dev-zero
- glibc提供的mmap与linux中的 sys_mmap的联动
- [以用户角度去应用内核空间内存]
- [以用户角度去应用用户空间内存]
以文件系统FS角度分析 启动
以 无init_xxx技术 的启动流程为研究对象
start_kernel
vfs_caches_init_early
vfs_caches_init
mnt_init
init_rootfs //注册 rootfs 文件系统
init_mount_tree
kernel_init
prepare_namespace
mount_root //挂载真正的文件系统(在这里以root=/dev/mmcblk0p2中的rootfstype=ext3为例,该文件系统根目录有/linuxrc)
init_post
run_init_process(execute_command) //内核参数为init=/linuxrc
- 文件系统启动总览
- 第一阶段 start_kernel 阶段文件系统的初始化
- [第二阶段 kernel_init 阶段文件系统的初始化到挂载真正的文件系统]
- linuxrc的加载及运行-run_init_process
- 从流程去熟悉文件系统1-挂载
- [从流程去熟悉文件系统2-文件操作]
- [从流程去熟悉文件系统3-search&层级结构]
- [从流程去熟悉文件系统4-文件IO]
在文件IO时会用 file_operations 中的成员去访问 文件
所有磁盘文件系统中的 文件 都共用一个 file_operations
大部分内存文件系统的 文件 都共用一个 file_operations
/dev下的 文件系统中的 cdev 文件 每个文件有一个 file_operations
open流程中,对于 init_special_inode // 例如 /dev 下的 特殊文件系统的文件
const struct file_operations def_chr_fops = {
.open = chrdev_open,
SyS_open->do_sys_open->do_filp_open->path_openat->do_last->vfs_open->do_dentry_open->chrdev_open
chrdev_open
fops = fops_get(p->ops);
replace_fops(filp, fops);
filp->f_op->open(inode, filp);
- 文件系统的访问加速及一致性策略
- [文件系统访问加速1-dentry]
- [文件系统访问加速2-address_space]
当读写(write read,非mmap)时,我们将磁盘数据缓存到 内存的物理页(物理页由struct page描述)
address_space 是用来管理 这些 struct apge 的
address_space 直接挂在了 file结构体下,不用复杂管理
page 由 radix_tree 管理
- [文件的访问技术]
1. 直接读写磁盘 // 缺点是每次读写都要陷入内核空间,都要转动磁盘
2. 页缓存技术 // 缺点是每次读写都要陷入内核空间
3. 页缓存技术+fread/fwrite // 缺点是增加了数据在不同缓冲区复制的次数
4. mmap技术 // 优点 : 减少系统调用和内存复制的次数
通过fd 访问 内存(保存内核信息) 的方式 共分以下几种
1. open mmap
2. open write read close
3. userfaultfd
4. memfd_create和fd跨进程共享
通过fd 访问 文件(保存在硬盘上) 的方式 共分为以下几种
1. open mmap
2. open write read close
IO 的同步和异步
- [IO 同步/异步 阻塞/非阻塞 概念]
- [read & write 阻塞IO]
- [read & write 非阻塞IO]
- [select,pselect,poll,epoll 多路复用]
- [信号驱动式IO]
- [异步非阻塞 IO]
-
[文件系统性能]
-
真实文件系统分析
磁盘文件系统比较好理解
网络文件系统暂时可以不用理解
但是内存文件系统类别比较多,各种内存文件系统都有,不知道为什么要分这么多类别
其中有 shmem tmpfs ramfs devtmpfs sysfs kernfs udevfs procfs debugfs devpts tracefs
cgroup pstore systemd-1 hugetlbfs mqueue sunrpc fusectl configfs nfsd binfmt_misc gvfsd-fuse
shmem tmpfs ramfs devtmfps 比较混乱
devtmpfs 的底层实现 用了 ramfs 和 shmem
tmpfs 的底层实现 用了 ramfs 和 shmem
系统启动过程中,挂载了
1. tmpfs
2. rootfs
3. bdev_cache_init
4. nsfs_init
5. devtmpfs
ARM异常分析
单核心的soc 的话,其实运行流程很单纯
包含
1. A进程代码
2. B进程代码
3. AB 系统调用(异常3)
4. AB 系统调用后进入内核的代码
5. 调度
6. 其他异常(异常1 2 4 5 6 7 8)
其他的就没了 // (由于会有异常及调度,所有会有竞态,所以需要同步)
多核心的soc,其实和这个一样
但是 多核心 相比 单核心,多了
1. 核间通信(应该归入异常范畴)
2. 核间同步
3. 多核boot
另外,会在 增加 调度方面的功能: cpu绑定,cpu间调度之类
- 异常1 00 reset 以 reset 按键为例
- 异常2 04 Undefined instructions
- 异常3 08 swi 即 系统调用发生时 的 流程,busybox->glibc->硬件->kernel->用户空间,以reboot为例
- [异常4 0c Prefetch Abort]
- 异常5 10 Data Abort 以缺页异常为例
- [异常6 14 null
- 异常7 18 irq 即 中断发生时的流程,以vic为例
- 异常8 1c fiq
linux对ARM异常的处理总体分析
- [每种处理方式中相同的部分]
- [中断异常的处理方式-底半部]
- [要不要结束,怎么结束]
linux 异常分析
除0 : SIGFPE
未对齐的数据访问 :
空指针的读写、写rodata section : SIGSEGV
prefetch abort
竞态与(内核)同步
- 并发 竞态 与 同步 总览
- [各种同步机制的关系及异同及使用场景]
- per-cpu的实现
- atomic bit int 64位 的实现
- 禁中断/中断屏蔽的实现
- 禁抢占的实现
- 禁软中断的实现
- 自旋锁的实现
- 读写锁的实现
- 顺序锁的实现
- 信号量(count=1)的实现
- 读写信号量的实现
- 互斥锁的实现
- [RCU的实现]
- [大内核锁BLK的实现(被遗弃了)
事件的同步
- "事件的同步"与"内核同步"的关系
- [sleep]
- 信号量(count初始化为0)
- [等待队列]
- [completion]
进程通信分析
linux 提供几种通信方式
1. 信号
2. 管道
3. 有名管道
4. 套接字
5. 信号量
6. 消息队列
7. 共享内存
A.dbus // dbus 基于 套接字
B.signalfd timerfd eventfd // 基于 anon inode fs
其中 信号量 消息队列 共享内存 posix 提供一套 , XSI(systemv) 提供一套
共享内存的实现 有很多种
1.posix mmap && open mmap
2.XSI(systemv)
3.memfd_create和fd跨进程共享
4.dma-buf
系统调用
文件格式
文件系统负责管理 文件,而不负责 解析文件里面的内容
linux内核调试&性能调试
1. printk
2. syslog
3. console
4. syslogd
5. klogd
6. kmesg
7. 动态打印
8. dump_stack
---
9. 内核参数& CONFIG
---
10. procfs
11. sysctl
12. sysfs
13. debugfs
14. top/htop free
---
15. gdb-with-jtag
16. kdb
17. kgdb
10.kgtp
---
10.BUG&BUG_ON
11.oops&panic
10.kdump(based on kexec)&crash & kcore
10.SysRq magic key
---
11.kprobe & systemtap
12.ftrace(trace-cmd)
13.perf & eBPF
14.LTTng
15.分析工具:火焰图 https://github.com/brendangregg/FlameGraph
- 1. printk
- 3. 动态打印
- 9. procfs
- 11. sysfs
- 12. debugfs
- 6. gdb-with-jtag
- 7. kdb
- 8. kgdb
- 10.BUG&BUG_ON
- 11.oops&panic
- 12.ftrace(trace-cmd)
LKM 的实现
- [LKM是什么]
- module elf命令文件的加载及执行