Linux启动过程简略分析-start_kernel部分代码阅读

Linux 启动过程分析

源代码和工具

kernel.org上可以下载各个版本的Linux.

概述

简单的说, 电脑加电启动后, 会进行自检(BIOS), 然后根据启动顺序, 依次检查可启动设备, 将找到的第一个可启动设备中特定区域内的内容(MBR), 拷贝到内存指定位置, 然后跳转到这个指定位置运行.到此, 软件系统才开始进行启动.软件系统启动分很多阶段, 但是在这个时候, 可以暂时分为两个阶段:加载阶段, 运行阶段.由于每代计算机都要兼容上一代计算机, 硬件无法把操作系统内核一次性全部加载到内存中, 而且, 内核也需要按照自己的需求, 将一些内容加载到特定内存位置, 所以, 在加载阶段, 计算机硬件加载的只是一个操作系统自己定制的加载器.这个加载器会收集一部分硬件信息, 为内核运行准备好环境, 然后将内核文件加载到指定的内存区域里, 然后在执行加载好的内核.有的操作系统会有两段加载过程, 第一段加载过程完成必要的初始化后加载第二段启动过程, 第二段加载过程就可以提供一个界面, 使用户能设置启动参数, 最后根据向内核传递的设置参数, 加载内核, 影响内核的工作方式.

操作系统有很多依赖体系的部分. 比如体系对内存的管理, 启动流程, 设备通信方式等等.从遥控器到大型机, 有太多的体系结构了.没必要了解每个体系结构.所以, 重要的部分应该是独立于体系结构的部分和操作系统如何处理与体系结构通信的部分, 这样才能更快地理解内核, 移植内核.

在进行一系列初始化(这部分严重依赖体系, 所以在/arch/x86目录下)之后, 进入start_kernel, 可以认为该部分对体系的依赖已经不是很大. 在这里, , 只提供了初始化的通用总体流程, 在流程中执行的各种操作, 会根据体系不同, 进行相应的条件编译. 从start_kernel开始, 就是使用C语言对内核的各个部分进行初始化, 最后进入rest_init, 将自己变为IDLE运行.在这个过程中要经过各种针对体系的初始化, 以支持操作系统的功能.start_kernel包括对硬件的初始化, 获取体系规格, 设置体系工作方式, 还包括对内核本身的初始化, 各种数据结构的初始化, 各种机制的初始化等.由于某些依赖于硬件, 比如任务调度依赖时钟中断, 所以要先初始化一部分硬件. 但是初始化某些硬件的时候, 也需要某些信息才能进行, 比如多核处理器上的调度方法和单核CPU的调度算法有所不同, 所以在调度之前要获取硬件规格.加之系统部件之间的相互依赖, 所以初始化的过程很复杂.每个部分的初始化可能分为很多阶段.

调试

在linux代码目录下执行make menuconfig进行设置, 选择确保kernel hacking -> Compile-time checks and compiler options -> Compile the kernel with debug info选中, 然后在linux目录下执行qemu -kernel ./arch/x86/boot/bzImage -s -S, 在另一个终端中执行gdb, 然后输入file ./linux-3.18.6/vmlinux, target remote :1234, b start_kernel, layout split, c, 之后就会停在start_kernel入口出. 其中file命令是加载要调试的文件, target是连接调试目标, b是设置断点, layout设置gdb的显示布局, c是运行被调试的程序.

调试过程截图

代码分析

start_kernel

在start_kernel之前, 就将task 0设置完毕. 由于对init_task来说, 很多部分是已知的, 所以用静态变量来设置struct task_struct init_task = INIT_TASK(init_task);(/init/init_task.c). 每个task记录了该task可以运行在哪个CPU上, 内存空间(mm_struct),

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
if (is.null(sub.caption)) { cal <- x$call if (!is.na(m.f <- match("formula", names(cal)))) { cal <- cal[c(1, m.f)] names(cal)[2L] <- "" } cc <- deparse(cal, 80) nc <- nchar(cc[1L], "c") abbr <- length(cc) > 1 || nc > 75 sub.caption <- if (abbr) paste(substr(cc[1L], 1L, min(75L, nc)), "...") else cc[1L] } place_ids <- function(x_coord, y_coord, offset, dif_pos_neg){ extreme_points <- as.vector(Rfast::nth(abs(y_coord), k = id.n, num.of.nths = id.n, index.return = TRUE, descending = TRUE)) if(dif_pos_neg){ idx_x_pos <- extreme_points[which(y_coord[extreme_points] >= 0)] idx_x_neg <- setdiff(extreme_points, idx_x_pos) idx_y_pos <- y_coord[idx_x_pos] idx_y_neg <- y_coord[idx_x_neg] idx_x_pos_id <- x_coord[idx_x_pos] idx_x_neg_id <- x_coord[idx_x_neg] if(length(idx_x_pos)>0){ graphics::text(idx_x_pos_id, idx_y_pos, labels = labels.id[idx_x_pos], col = col.id, cex = cex.id, xpd = TRUE, pos = 3, offset = offset) } if(length(idx_x_neg)>0){ graphics::text(idx_x_neg_id, idx_y_neg, labels = labels.id[idx_x_neg], col = col.id, cex = cex.id, xpd = TRUE, pos = 1, offset = offset) } } else{ idx_x <- extreme_points idx_y <- y_coord[idx_x] idx_x_id <- x_coord[idx_x] labpos <- label.pos[1 + as.numeric(idx_x_id > mean(range(x_coord)))] graphics::text(idx_x_id, idx_y, labels = labels.id[idx_x], col = col.id, cex = cex.id, pos = labpos, xpd = TRUE, offset = offset) } } one.fig <- prod(graphics::par("mfcol")) == 1 if (ask) { oask <- grDevices::devAskNewPage(TRUE) on.exit(grDevices::devAskNewPage(oask)) }
06-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值