跳到主要内容Linux内核源代码深度解析:从设备树到电源管理的完整技术栈 | 极客日志C算法
Linux内核源代码深度解析:从设备树到电源管理的完整技术栈
综述由AI生成深入解析了 Linux 内核核心子系统,包括设备树(DTB)的启动解析与更新机制、Kconfig 配置与编译流程、LCD Framebuffer 驱动架构及寄存器配置、电源管理挂起状态机与模式差异,以及 CFS 与实时调度器的公平性与优先级算法实现。通过代码级分析展示了内核构建、驱动开发与系统优化的关键技术栈。
落日余晖26 浏览 1. 设备树 DTB 文件的内核处理机制
1.1 DTB 文件在内核启动阶段的解析过程
Linux 内核在启动时通过 early_init_dt_scan 函数解析设备树,以下是关键的内核源代码:
void __init setup_arch(char **cmdline_p) {
early_init_dt_scan_nodes();
early_init_dt_scan_memory();
}
void __init early_init_dt_scan_nodes(void) {
of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
of_scan_flat_dt(early_init_dt_scan_root, NULL);
of_scan_flat_dt(early_init_dt_scan_memory, NULL);
}
bool __init early_init_dt_scan_memory(void) {
int node;
const char *type;
int len;
for (node = 0; node < INT_MAX; node++) {
type = of_get_flat_dt_prop(node, "device_type", &len);
if (!type) continue;
if (strcmp(type, "memory") == 0) {
early_init_dt_add_memory_arch(node);
}
}
return true;
}
内核处理流程说明:
- 启动时通过
early_init_dt_scan_nodes() 扫描设备树的所有节点
- 使用 回调机制遍历设备树
of_scan_flat_dt()
识别 memory 节点并调用 early_init_dt_add_memory_arch() 注册内存区域1.2 DTB 文件替换与内核重新加载
struct device_node *of_fdt_unflatten_tree(const unsigned long *blob, struct device_node *dad) {
struct device_node *node;
node = of_fdt_unflatten_tree(blob, dad);
if (!node) return ERR_PTR(-EINVAL);
return node;
}
int of_update_property(struct device_node *np, struct property *newprop) {
struct property *oldprop;
oldprop = of_find_property(np, newprop->name, NULL);
if (oldprop) {
return of_update_property(np, newprop);
} else {
return of_add_property(np, newprop);
}
}
2. 内核配置与编译的核心机制
2.1 Kconfig 配置系统解析
内核配置系统通过 Kconfig 文件定义配置选项:
config ARM64
bool "ARM64 (AArch64) Support"
select ACPI
select ARCH_HAS_DEBUG_VIRTUAL
select ARCH_SUPPORTS_INT128
if CC_HAS_INT128
config ARM64_4K_PAGES
bool "4KB page size"
default y
config ARM64_64K_PAGES
bool "64KB page size"
depends on !ARM64_4K_PAGES
struct property *prop_alloc(enum prop_type type, struct symbol *sym) {
struct property *prop;
prop = xmalloc(sizeof(*prop));
prop->type = type;
prop->sym = sym;
prop->menu = NULL;
prop->expr = expr_alloc_symbol(sym);
return prop;
}
struct expr *expr_alloc_symbol(struct symbol *sym) {
struct expr *e = xmalloc(sizeof(*e));
e->type = E_SYMBOL;
e->left.sym = sym;
return e;
}
2.2 内核编译过程关键代码
vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE
+$(call if_changed,link-vmlinux)
modules: $(vmlinux-deps) $(if $(KBUILD_BUILTIN),vmlinux) FORCE
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
dtbs: scripts
$(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@
vmlinux_link() {
local lds="${objtree}/${KBUILD_LDS}"
# 调用链接器
${LD} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \
-T ${lds} ${KBUILD_VMLINUX_OBJS} \
--start-group ${KBUILD_VMLINUX_LIBS} --end-group
}
3. LCD 驱动与显示子系统架构
3.1 Framebuffer 驱动核心实现
LCD 驱动的 framebuffer 接口实现:
static const struct file_operations fb_fops = {
.owner = THIS_MODULE,
.read = fb_read,
.write = fb_write,
.unlocked_ioctl = fb_ioctl,
.mmap = fb_mmap,
.open = fb_open,
.release = fb_release,
};
static struct fb_ops xxxfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = xxxfb_check_var,
.fb_set_par = xxxfb_set_par,
.fb_setcolreg = xxxfb_setcolreg,
.fb_blank = xxxfb_blank,
.fb_pan_display = xxxfb_pan_display,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
};
3.2 S3C2410 LCD 控制器寄存器配置
static struct s3c2410fb_mach_info smdk2410_lcd_cfg __initdata = {
.regs = {
.lcdcon1 = S3C2410_LCDCON1_CLKVAL(0x0) | S3C2410_LCDCON1_MMODE | S3C2410_LCDCON1_PNRMODE_TFT | S3C2410_LCDCON1_BPPMODE_16,
.lcdcon2 = S3C2410_LCDCON2_VBPD(1) | S3C2410_LCDCON2_LINEVAL(239) | S3C2410_LCDCON2_VFPD(1) | S3C2410_LCDCON2_VSPW(1),
.lcdcon3 = S3C2410_LCDCON3_HBPD(1) | S3C2410_LCDCON3_HOZVAL(319) | S3C2410_LCDCON3_HFPD(1),
.lcdcon4 = S3C2410_LCDCON4_HSPW(1) | S3C2410_LCDCON4_MVAL(0),
.lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_INVVLINE | S3C2410_LCDCON5_INVVFRAME | S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP,
},
.width = 320,
.height = 240,
.xres = 320,
.yres = 240,
};
4. 电源管理 Suspend 功能深度剖析
4.1 Suspend 状态机与处理流程
static int suspend_enter(suspend_state_t state) {
int error;
error = suspend_freeze_processes();
if (error) goto Unlock;
error = suspend_devices_and_enter(state);
if (error) goto Thaw;
if (!error) {
error = platform_suspend_enter(state);
if (error) goto Resume_devices;
}
Thaw:
suspend_thaw_processes();
Unlock:
return error;
}
int suspend_devices_and_enter(suspend_state_t state) {
int error;
suspend_console();
error = dpm_suspend_start(PMSG_SUSPEND);
if (error) {
pr_err("Some devices failed to suspend ");
goto Resume_console;
}
error = suspend_enter(state);
Resume_console:
resume_console();
return error;
}
4.2 三种 Suspend 模式的实现差异
static const struct platform_suspend_ops *suspend_ops;
const struct platform_suspend_ops pm_suspend_ops = {
.valid = suspend_valid_only_mem,
.begin = suspend_begin,
.prepare = suspend_prepare,
.prepare_late = suspend_prepare_late,
.enter = suspend_enter,
.wake = suspend_finish,
.end = suspend_end,
.recover = suspend_recover,
};
int freeze_processes(void) {
int error;
error = suspend_freeze_processes();
if (!error) error = suspend_freeze_kernel_threads();
return error;
}
static int standby_enter(suspend_state_t state) {
return pm_suspend(state);
}
static int mem_suspend_enter(suspend_state_t state) {
return suspend_enter(state);
}
5. 实时调度器核心算法实现
5.1 CFS 调度器公平性算法
static void __sched notrace __schedule(bool preempt) {
struct task_struct *prev, *next;
struct rq *rq;
int cpu;
cpu = smp_processor_id();
rq = cpu_rq(cpu);
prev = rq->curr;
next = pick_next_task(rq, prev, &rf);
if (likely(prev != next)) {
rq = context_switch(rq, prev, next, &rf);
}
}
static struct task_struct * pick_next_task_fair(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) {
struct cfs_rq *cfs_rq = &rq->cfs;
struct sched_entity *se;
struct task_struct *p;
se = pick_next_entity(cfs_rq);
p = task_of(se);
return p;
}
static void update_curr(struct cfs_rq *cfs_rq) {
struct sched_entity *curr = cfs_rq->curr;
u64 now = rq_clock_task(rq_of(cfs_rq));
u64 delta_exec;
if (unlikely(!curr)) return;
delta_exec = now - curr->exec_start;
curr->exec_start = now;
curr->vruntime += calc_delta_fair(delta_exec, curr);
update_min_vruntime(cfs_rq);
}
5.2 实时调度器优先级处理
static void __sched notrace __schedule_rt(bool preempt) {
struct task_struct *p;
struct rt_rq *rt_rq;
p = pick_next_rt_entity(rt_rq);
if (p) {
set_next_rt_entity(rt_rq, p);
}
}
const struct sched_class rt_sched_class = {
.next = &fair_sched_class,
.enqueue_task = enqueue_task_rt,
.dequeue_task = dequeue_task_rt,
.yield_task = yield_task_rt,
.check_preempt_curr = check_preempt_curr_rt,
.pick_next_task = pick_next_task_rt,
.put_prev_task = put_prev_task_rt,
.set_curr_task = set_curr_task_rt,
.task_tick = task_tick_rt,
.get_rr_interval = get_rr_interval_rt,
.prio_changed = prio_changed_rt,
.switched_to = switched_to_rt,
};
static int rt_mutex_adjust_prio_chain(struct task_struct *task, int deadlock_detect, struct rt_mutex *orig_lock, struct rt_mutex_waiter *orig_waiter) {
struct task_struct *top_task = task;
struct rt_mutex *lock;
while (top_task->pi_blocked_on) {
lock = top_task->pi_blocked_on->lock;
if (lock->owner) {
rt_mutex_setprio(lock->owner, top_task->prio);
}
top_task = lock->owner;
}
return 0;
}
6. 内核编译系统架构解析
6.1 内核构建系统的 Makefile 架构
VERSION = 5
PATCHLEVEL = 15
SUBLEVEL = 0
EXTRAVERSION = -rc1
NAME = Trick or Treat
PHONY += _all
_all: all
%config: scripts_basic outputmakefile FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $@
KBUILD_VMLINUX_OBJS := $(head-y) $(init-y) $(core-y) $(libs-y) $(drivers-y) $(net-y)
vmlinux: $(KBUILD_VMLINUX_OBJS) $(KBUILD_LDS) FORCE
+$(call if_changed,link-vmlinux)
6.2 Kbuild 系统模块编译机制
$(obj)/%.ko: $(obj)/%.o FORCE
$(call if_changed,ld_ko_o)
quiet_cmd_ld_ko_o = LD [M] $@
cmd_ld_ko_o = $(LD) -r $(LDFLAGS) $(LDFLAGS_MODULE) -o $@ \
$(filter-out FORCE,$^)
__modinst: $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst
static int load_module(struct load_info *info, const char __user *uargs, int flags) {
struct module *mod;
int err;
err = module_sig_check(info, flags);
if (err) goto free_copy;
mod = layout_and_allocate(info, flags);
if (IS_ERR(mod)) {
err = PTR_ERR(mod);
goto free_copy;
}
err = apply_relocations(mod, info);
if (err) goto free_module;
err = do_init_module(mod);
if (err) goto free_module;
return 0;
free_module:
free_module(mod);
free_copy:
return err;
}
以上代码分析展示了 Linux 内核从设备树处理到电源管理、从调度器实现到编译系统的完整技术栈。每个子系统都通过精心设计的架构和算法来确保系统的稳定性、性能和功能完整性。通过深入理解这些内核源代码,开发者能够更好地进行内核定制、驱动开发和系统优化工作。
相关免费在线工具
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- Gemini 图片去水印
基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown转HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
- HTML转Markdown
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online