1. 总览 这里以ARM64为例。 在内核的起始阶段,还没有进程和线程的概念,在开启MMU之后,__primary_switched的第一步就是将init_task的地址写到sp_el0,这个时候就可以用get_current()或者curent获取到0号线程的task_struct了。在0号线程的上下文,完成调度器的相关初始化之后,创建1号和2号线程,然后开启调度器,init_task自此进入idle状态。 这里看几个概念: 0号线程:对应init_task结构体,名字为swapper,在多处理器中,名称为swapper/<id>,负责内核的一些基础的初始化工作。 1号线程:由0号线程创建,最初的函数为kernel_init,运...
1. 1号进程的内核态 1号进程首先运行在内核态,其函数是kernel_init,这里简单介绍一下其工作: 非bootcpu相关初始化 页分配器初始化的收尾工作 驱动子系统和设备树初始化 调用__initcall指定的初始化函数 挂载根文件系统 是否__init指定的内存 执行用户态init程序 2. 1号进程内核态到用户态的切换 kernel_init最后通过kernel_execve函数执行用户程序,完成内核态到用户态的切换。 这里以elf格式的init程序为例简单说明一下kernel_execve的工作流程:kernel_execve会申请新的mm_struct,记录init程序的代码段和数据段,将当前进程内核栈中记录的pc...
1. 2号线程kthreadd Linux内核规定,所有的线程必须由已存在的线程创建出来,也就是要求所有的task_struct都需要在已有的task_struct上复制出来。Linux可以通过kernel_thread来创建内核线程,这个函数会复制当前线程的task_struct。如果任由各个子系统或驱动自己调用kernel_thread来创建线程,那在创建内核线程时current所指向的task_struct是不确定的。为了解决这一问题,Linux内核将所有内核线程的创建交给固定的线程来做,这个线程就是2号线程kthreadd。 2. 内核线程创建的接口 内核为开发者提供了两个创建内核线程的宏kthread_create...
initcall和module_init
bus/class/device/driver
设备树的展开unflatten_device_tree
从“device_node tree”到“device tree”
1. 数据结构简介 内核版本:linux-6.1 内核文档:Everything you never wanted to know about kobjects, ksets, and ktypes — The Linux Kernel documentation 在Linux内核中,kobject、kset和kobj_type是用于管理和表示kobject的数据结构。kobject是设备驱动模型的基石,sysfs和uevent也与kobject密切相关。 1.1. kobject struct kobject表示一个对象,包含了一些基本属性,通常会内嵌在其他结构体中来表示不同的实例。每个kobject都会在sysfs中呈现出一个...
timekeeping
1. thermal简介 thermal子系统主要用来监测和调节CPU、GPU等芯片或设备的温度。三个主要结构体的关系:从thermal_zone_device获取温度后,根据governor指定的策略,来控制thermal_cooling_device进行温度调节。 结构体 描述 举例 struct thermal_zone_device 对温度调节域的抽象,包含配置信息和传感器信息 NTC、Temperature Sensor ADC(TSADC) struct thermal_cooling_device 用于冷却的设备 CPU、GPU、风扇 struct thermal_governor...