朱宇轲 + 原创作品转载请注明出处 + 《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内核代码分析操作系统启动过程的更多相关文章

  1. Linux与Windows xp操作系统启动过程

    Linux启动过程: 第一步,加载BIOS,当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它.这是因为BIOS中包含了CPU的相关信息.设备 ...

  2. linux内核与分析 心得与体会

    作业目录: (1)计算机是如何工作的:http://www.cnblogs.com/20135335hs/p/5213394.html (2)操作系统是如何工作的:http://www.cnblogs ...

  3. 第三次阅读赵炯博士的《linux内核代码完全注释》:序

    这是我第三次阅读linux内核代码完全注释了,当然前两次也没有读完,第一次读到第五章,第二次第七章. 所以说,赵炯博士对我最大的帮助时介绍了intel386的结构,以及内核编程的方法. 至于真正的内核 ...

  4. 通过gdb跟踪Linux内核装载和启动可执行程序过程

    作者:吴乐 山东师范大学 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验目的:通过对一个简单的可执 ...

  5. Linux内核源代码分析方法

    Linux内核源代码分析方法   一.内核源代码之我见 Linux内核代码的庞大令不少人"望而生畏",也正由于如此,使得人们对Linux的了解仅处于泛泛的层次.假设想透析Linux ...

  6. Linux内核(3) - 分析内核源码如何入手(下)

    下面的分析,米卢教练说了,内容不重要,重要的是态度.就像韩局长对待日记的态度那样,严谨而细致. 只要你使用这样的态度开始分析内核,那么无论你选择内核的哪个部分作为切入点,比如USB,比如进程管理,在花 ...

  7. linux 内核的链表操作(好文不得不转)

    以下全部来自于http://www.ibm.com/developerworks/cn/linux/kernel/l-chain/index.html 无任何个人意见. 本文详细分析了 2.6.x 内 ...

  8. linux内核代码的编写初步以及makefile的配置

    在linux内核代码开发中,头文件不能包含标准C头文件,只能采用GNC标准 而且内核开发中没有main函数,只有init 和 exit ,这是每个内核模块中必须要包含的函数模块. 在GNU C标准中, ...

  9. 《Linux内核与分析》第五周

    20135130王川东 一.给MenuOS增加time和time-asm命令 命令:1.强制删除:rm menu -rf 2.克隆:git clone (后跟需要克隆数据所在的位置) 3.自动编译,自 ...

随机推荐

  1. oracle schema object

    Oracle supplies many PL/SQL packages with the Oracle server to extend database functionality and pro ...

  2. 【转】Asp.net中时间格式化的6种方法详细总结

    1. 数据控件绑定时格式化日期方法: 代码如下: <asp:BoundColumn DataField="AddTime" HeaderText="添加时间&quo ...

  3. ORACLE 常用字符函数

    ORACLE 常用字符函数1 ASCII(arg1)返回参数arg1的十进制数字表示.如果数据库设置为ASCII,则采用的是ASCII码字符.如果设置为EBCDIC,则采用的是EBCDIC字符 sel ...

  4. 工作中简单又实用的vim配置

    set number syntax enable set tabstop=4 set shiftwidth=4 set noexpandtab set cindent set autoindent s ...

  5. 【python】sys.argv[]的用法

    在学python的过程中,一直弄不明白sys.argv[]的意思,虽知道是表示命令行参数,但还是有些稀里糊涂的感觉. 今天又好好学习了一把,总算是大彻大悟了. Sys.argv[]是用来获取命令行参数 ...

  6. jQuery实现登录提示

    实现效果:将鼠标聚焦到邮箱地址文本框时,文本框 内的"请输入邮箱地址"文字将被清除:   若没有输入任何内容,鼠标移除后邮箱地址文本框被还原. <!DOCTYPE html& ...

  7. 【VNC】Ubuntu14.04LTS下安装VNC View

    # apt-get install tightvncserver vnc4server gnome-panel gnome-settings-daemon metacity nautilus gnom ...

  8. Python 数据排序和列表迭代和列表推导应用

    1.In-place sorting 原地排序 data=[6,4,5,2,3,1] print ('before sort', data) data.sort() print ('after sor ...

  9. android学习笔记六——Spinner

    注:参考http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0105/2264.html Spinner ==> Spinner ...

  10. C#:基于WMI查询USB设备

    来源:http://blog.csdn.net/jhqin/article/details/6734673 /* ------------------------------------------- ...