从linux内核代码分析操作系统启动过程
朱宇轲 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
在本次的实验中,我们将通过简单分析Linux内核代码来探讨操作系统的启动过程。
计算机启动的过程其实在Andrew S.Tanenbaum所著的《现代操作系统》(中文版第18页)中就有大略的描述:
1.计算机启动时,存储在RAM中的BIOS程序检查计算机的所有设备,包括RAM、键盘、鼠标、ISA及PCI总线上的设备等,这些设备将被记录下来。
2.BIOS寻找可引导介质,从软盘、CD或硬盘中加载操作系统,将控制权交给操作系统中的引导程序。
3.操作系统询问BIOS,获得各个设备的配置信息,然后开始进行初始化工作。
而我们今天主要是分析linux内核在进行初始化工作时的步骤,首先是实验代码和截图:
进入实验楼的系统中,首先进入linux内核文件,并启动内核镜像:
cd LinuxKernel/
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
然后另开一个shell来利用gdb调试内核代码:
gdb
(gdb)file linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加载符号表
(gdb)target remote:1234 # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行
(gdb)break start_kernel # 断点的设置可以在target remote之前,也可以在之后
通过输入"c"来启动内核初始化,当执行到break设定的函数时会自动停止。如图所示。
下面我们来对内核初始化过程进行简单分析。
内核的初始化过程由start_kernel函数开始,至第一个用户进程init结束,调用了一系列的初始化函数对所有的内核组件进行初始化。其中,start_kernel、rest_init、kernel_init、init_post等4个函数构成了整个初始化过程的主线。如下图所示:
首先我们分析start_kernel:
注意第510行,set_task_stack_end_magic设置了第0号进程的进程管理块,也就是init_task。它是一个比较特殊的进程,其他进程一般要通过fork命令来完成,只有它是由内核开发者人为制造出来的,它的初始化由arch/x86/kernel/init_task.c中的代码来完成。
接下来则进行了一系列的初始化工作,直到执行到最后一行,进入rest_init函数。
static noinline void __init_refok rest_init(void)
{
int pid; rcu_scheduler_starting();
/*
* 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);
numa_default_policy();
pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
rcu_read_lock();
kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
rcu_read_unlock();
complete(&kthreadd_done); /*
* The boot idle thread must execute schedule()
* at least once to get things moving:
*/
init_idle_bootup_task(current);
schedule_preempt_disabled()
/* Call into cpu_idle with preempt disabled */
cpu_startup_entry(CPUHP_ONLINE);
}
在rest_init中,系统开始真正地产生进程。第11行代码“kernel_thread(kernel_init, NULL, CLONE_FS);”就是具体的创建进程的语句。
kernel_init函数将完成设备驱动程序的初始化,并调用init_post函数启动用户空间的init进程。
而此时,我们第一个创建的进程init_task已经完成了自己的使命,它被start_kernel函数中的shed_init()函数转化为一个idle task,当运行队列中没有别的进程时,它便会进入不断的循环,直到运行队列中加入新的进程时才将控制权切换到新进程上。由此内核就启动完毕了。
参考资料
《现代操作系统》 Andrew S. Tanenbaum 机械工业出版社
http://book.51cto.com/art/201007/213598.htm
Linux内核中的init_task进程和idle进程
从linux内核代码分析操作系统启动过程的更多相关文章
- Linux与Windows xp操作系统启动过程
Linux启动过程: 第一步,加载BIOS,当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它.这是因为BIOS中包含了CPU的相关信息.设备 ...
- linux内核与分析 心得与体会
作业目录: (1)计算机是如何工作的:http://www.cnblogs.com/20135335hs/p/5213394.html (2)操作系统是如何工作的:http://www.cnblogs ...
- 第三次阅读赵炯博士的《linux内核代码完全注释》:序
这是我第三次阅读linux内核代码完全注释了,当然前两次也没有读完,第一次读到第五章,第二次第七章. 所以说,赵炯博士对我最大的帮助时介绍了intel386的结构,以及内核编程的方法. 至于真正的内核 ...
- 通过gdb跟踪Linux内核装载和启动可执行程序过程
作者:吴乐 山东师范大学 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验目的:通过对一个简单的可执 ...
- Linux内核源代码分析方法
Linux内核源代码分析方法 一.内核源代码之我见 Linux内核代码的庞大令不少人"望而生畏",也正由于如此,使得人们对Linux的了解仅处于泛泛的层次.假设想透析Linux ...
- Linux内核(3) - 分析内核源码如何入手(下)
下面的分析,米卢教练说了,内容不重要,重要的是态度.就像韩局长对待日记的态度那样,严谨而细致. 只要你使用这样的态度开始分析内核,那么无论你选择内核的哪个部分作为切入点,比如USB,比如进程管理,在花 ...
- linux 内核的链表操作(好文不得不转)
以下全部来自于http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/index.html 无任何个人意见. 本文详细分析了 2.6.x 内 ...
- linux内核代码的编写初步以及makefile的配置
在linux内核代码开发中,头文件不能包含标准C头文件,只能采用GNC标准 而且内核开发中没有main函数,只有init 和 exit ,这是每个内核模块中必须要包含的函数模块. 在GNU C标准中, ...
- 《Linux内核与分析》第五周
20135130王川东 一.给MenuOS增加time和time-asm命令 命令:1.强制删除:rm menu -rf 2.克隆:git clone (后跟需要克隆数据所在的位置) 3.自动编译,自 ...
随机推荐
- Flowplayer-一款免费的WEB视频播放器
Flowplayer 是一个开源(GPL 3的)WEB视频播放器.您可以将该播放器嵌入您的网页中,如果您是开发人员,您还可以自由定制和配置播放器相关参数以达到您要的播放效果. Flowplayer支持 ...
- Android Afinal框架(二)
框架地址:https://github.com/yangfuhai/afinal 对应的源码: net.tsz.afinal.annotation.view.* FinalActivity Final ...
- sklearn基础知识-准备阶段
6.标签特征二元化 处理分类变量还有另一种方法,不需要通过OneHotEncoder,我们可以用LabelBinarizer. 这是一个阈值与分类变量组合的方法. In [1]: from sklea ...
- Kindle 实用技巧
1.Kindle Mate:可以连接kindle导出生词本,笔记,注释,超级棒. 2.把PDF发送到Kindle的时候,邮件主题写convert,这样系统会自动把PDF转换成适合Kindle阅读的格式 ...
- apache配置weblogic部署集群,多节点的项目和单节点项目并存 负载均衡
开启模块如下: LoadModule weblogic_module modules/mod_wl_22.so LoadModule lbmethod_byrequests_module module ...
- java提供的默认list排序方法-转
1.java提供的默认list排序方法 主要代码: List<String> list = new ArrayList();list.add("刘媛媛"); list. ...
- [原]网络库libevent在Visual Studio中的使用方法
libevent是一个事件触发的网络库,适用于windows.linux.bsd等多种平台,内部使用select.epoll.kqueue等系统调用管理事件机制.著名分布式缓存软件memcached也 ...
- android学习笔记22——Notification
Notification ==> Notification是显示在手机状态栏的消息,位于手机屏幕的最上方: 一般显示手机当前网络.电池状态.时间等: Notification所代表的是一种全局效 ...
- ros的相关link
http://markzhang.cn/blog/2014/08/19/ros-basic-setup/ http://blog.csdn.net/boliang319/article/details ...
- 水晶报表(web)表格信息展示
一.环境安装 开发工具使用VS2010+SAP Crystal Reports13_0+.NETformwork4.0 因为vs2010已经不再集成水晶报表,所以需要我们去找合适的版本下载http:/ ...