Linux内核设计第三周学习总结 跟踪分析Linux内核的启动过程
陈巧然 原创作品 转载请注明出处
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
实验步骤
登陆实验楼虚拟机http://www.shiyanlou.com/courses/195
打开shell终端,执行以下命令:
cd LinuxKernel/
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage-initrd rootfs.img
执行完毕后会弹出QEMU窗口,输出Linux内核启动信息
启动成功后界面显示MenuOS命令提示符
打开shell终端,执行以下命令:
cd LinuxKernel/
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage-initrd rootfs.img -s -S
关于-s和-S选项的说明:
-S freeze CPU at startup (use ’c’ to start execution) 在系统启动的时候冻结CPU,使用c键继续执行后续操作
-s shorthand for -gdb tcp::1234 打开远程调试端口,默认使用tcp协议1234端口,若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项
gdb
(gdb)filelinux-3.18.6/vmlinux # 在gdb界面中targe remote之前加载符号表
实验分析
本文以Linux3.19.1源代码为例分析。
分析./init/main.c源码文件start_kernel()函数
Linux内核启动代码大致分2部分:
一部分是硬件平台相关的,存放在./arch/目录下,以平台区分不同目录,比如x86平台就在./arch/x86/目录下,由汇编语言编写而成。
另一部分是硬件平台无关的,由C语言编写而成。
./init/main.c中的start_kernel()函数即是Linux内核启动过程由平台相关转为平台无关代码后第一个执行的函数,在这个函数中,Linux内核开始真正进入初始化阶段。
下面简单介绍其中的几个函数。(斜体字为源码,粗体字为解释)
/*
* Need to run as early as possible, to initialize the
* lockdep hash:
*/
lockdep_init();
lockdep是一个内核调试模块,用来检查内核互斥机制(尤其是自旋锁)潜在的死锁问题。
set_task_stack_end_magic(&init_task);
手工创建的PCB,0号进程即最终的idle进程。
/*
* Set up the the initial canary ASAP:
*/
boot_init_stack_canary();
canary值的是用于防止栈溢出攻击的堆栈的保护字。
trap_init();
对内核陷阱异常进行初始化。
mm_init();
初始化内核内存分配器。
/*
* Set up the scheduler prior starting any interrupts (such as the
* timer interrupt). Full topology setup happens at smp_init()
* time - but meanwhile we still have a functioning scheduler.
*/
sched_init();
初始化调度器数据结构,并创建运行队列。(一道作业题的答案:Linux源码start_kernel函数中调用进程调度初始化的是哪个函数?)
/* Do the rest non-__init'ed, we're now alive */
rest_init();
start_kernel()函数中调用的最后一个函数。
分析./init/main.c源码文件rest_init()函数
rest_init()函数的主要功能是创建并启动内核进程init,即第一个用户态进程。
int pid;
定义pid变量存放进程号
rcu_scheduler_starting();
RCU(Read-Copy Update)锁机制启动。
/*
* We need to spawn init first so that it obtains pid 1, however
* the init task will end up wanting to create kthreads, which, if
* we schedule it before we create kthreadd, will OOPS.
*/
kernel_thread(kernel_init, NULL, CLONE_FS);
init进程在此时创建好了,但是现在还不能调度它。
numa_default_policy();
设定NUMA(Non-Uniform Memory Access Architecture)系统的内存访问策略为默认。
pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
创建kthreadd内核线程,它的作用是管理和调度其它内核线程。
rcu_read_lock();
kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
获取kthreadd的线程信息,获取完成说明kthreadd已经创建成功。
rcu_read_unlock();
complete(&kthreadd_done);
通过一个complete变量(kthreadd_done)来通知kernel_init线程。
实验总结:
当计算机系统加电(Power on PC)后,BIOS代码被调用执行,然后开始调用执行Linux内核初始化代码,在平台相关的汇编代码执行完毕后会跳转到start_kernel()函数,开始真正的内核初始化,其中init_task创建了0号进程,即最终的idle进程,随后rest_init()函数创建了init进程,即1号进程,以及kthreadd进程,即2号进程,系统开始正常工作了。
Linux内核设计第三周学习总结 跟踪分析Linux内核的启动过程的更多相关文章
- Linux内核设计第三周——构造一个简单的Linux系统
Linux内核设计第三周 ——构造一个简单的Linux系统 一.知识点总结 计算机三个法宝: 存储程序计算机 函数调用堆栈 中断 操作系统两把宝剑: 中断上下文的切换 进程上下文的切换 linux内核 ...
- Linux内核设计第八周 ——进程的切换和系统的一般执行过程
Linux内核设计第八周 ——进程的切换和系统的一般执行过程 第一部分 知识点总结 第二部分 实验部分 1.配置实验环境,确保menu内核可以正常启动 2.进入gdb调试,在shedule和conte ...
- Linux内核设计第八周学习总结 理解进程调度时机跟踪分析进程调度与进程切换的过程
陈巧然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.视频内容 Linux ...
- Linux内核设计第五周学习总结 分析system_call中断处理过程
陈巧然原创作品 转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 使用gdb跟踪分析一 ...
- Linux内核设计第七周学习总结 Linux内核如何装载和启动一个可执行程序
陈巧然原创作品 转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-100002900 实验目的 使用gdb跟踪s ...
- Linux内核设计第六周学习总结 分析Linux内核创建一个新进程的过程
陈巧然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.实验过程 登陆实验楼 ...
- 《Linux内核分析》第三周学习报告
<Linux内核分析>第三周学习报告 ——构造一个简单的Linux系统MenuOS 姓名:王玮怡 学号:201351 ...
- 《Linux内核分析》第三周学习笔记
<Linux内核分析>第三周学习笔记 构造一个简单的Linux系统MenuOS 郭垚 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.stud ...
- LINUX内核分析第三周学习总结——构造一个简单的Linux系统MenuOS
LINUX内核分析第三周学习总结——构造一个简单的Linux系统MenuOS 张忻(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163. ...
随机推荐
- Spark之spark shell
前言:要学习spark程序开发,建议先学习spark-shell交互式学习,加深对spark程序开发的理解.spark-shell提供了一种学习API的简单方式,以及一个能够进行交互式分析数据的强大工 ...
- Linux系统网络安装——基于pxe+dhcp+nfs+tftp+kickstart
原文发表于:2010-09-05 转载至cu于:2012-07-21 一.原理简介 PXE(preboot execute environment)工作于Client/Server的网络模式,支持工作 ...
- 第五次ScrumMeeting博客
第五次ScrumMeeting博客 本次会议于10月29日(日)22时整在3公寓725房间召开,持续15分钟. 与会人员:刘畅.辛德泰.窦鑫泽.张安澜.赵奕. 1. 每个人的工作(有Issue的内容和 ...
- 软件工程 speedsnail 第二次冲刺10
20150527 完成任务:蜗牛碰到线后速度方向的调整:已经基本实现多方向的反射: 遇到问题: 问题1 反射角的问题 解决1 利用tan()三角函数 明日任务: 大总结.找到新问题.布置下一次冲刺方案
- 2016-2017 ACM-ICPC, NEERC, Northern Subregional Contest Problem I. Integral Polygons
题目来源:http://codeforces.com/group/aUVPeyEnI2/contest/229510 时间限制:2s 空间限制:256MB 题目大意: 给定一个凸多边形,有一种连接两个 ...
- “献给爱读书的中国人”——Amazon Kindle软件测评
“献给爱读书的中国人” ——Amazon Kindle软件测评 前不久我在网上看到了一篇印度工程师旅居上海时发表的一篇文章,题目叫做<令人忧虑:不阅读的中国人>,大致讲述的是世界上人们在飞 ...
- 继承&成员函数&覆盖
//成员函数. /* 当子父类中出现成员函数一模一样的情况,会运行子类的函数. 这种现象,称为覆盖操作.这时函数在子父类中的特性. 函数两个特性: 1,重载.同一个类中.overload 2,覆盖.子 ...
- Java单例模式&static成员变量 区别
当需要共享的变量很多时,使用static变量占用内存的时间过长,在类的整个生命周期. 而对象只是存在于对象的整个生命周期. //饿汉式 class Single//类一加载,对象就已经存在了. { ...
- iOS- Autolayout自动布局
1.前言 •在iOS程序中,大部分视图控制器都包含了大量的代码用于设置UI布局,设置控件的水平或垂直位置,以确保组件在不同版本的iOS中都能得到合理的布局 •甚至有些程序员希望在不同的设备使用相同的视 ...
- 在原有的基础之上,启用NAT模型
# 给虚拟主机实例添加一个网关 route add default gw 192.168.23.1 # 在宿主机打开网卡间转发功能 echo 1 > /proc/sys/net/ipv4/i ...