您的位置:首页 > 运维架构 > Linux

Linux内核分析-构造一个简单的Linux系统MenuOS

2016-03-12 18:38 507 查看

构造一个简单的Linux系统MenuOS

linux内核目录结构

arch目录包括了所有和体系结构相关的核心代码。它下面的每一个子目录都代表一种Linux支持的体系结构,例如i386就是Intel CPU及与之相兼容体系结构的子目录。PC机一般都基于此目录。

include目录包括编译核心所需要的大部分头文件,例如与平台无关的头文件在include/linux子目录下。

init目录包含核心的初始化代码(不是系统的引导代码),有main.c和Version.c两个文件。这是研究核心如何工作的好起点。

mm目录包含了所有的内存管理代码。与具体硬件体系结构相关的内存管理代码位于arch/*/mm目录下。

drivers目录中是系统中所有的设备驱动程序。它又进一步划分成几类设备驱动,每一种有对应的子目录,如声卡的驱动对应于drivers/sound。

ipc目录包含了核心进程间的通信代码。

modules目录存放了已建好的、可动态加载的模块。

fs目录存放Linux支持的文件系统代码。不同的文件系统有不同的子目录对应,如ext3文件系统对应的就是ext3子目录。

Kernel内核管理的核心代码放在这里。同时与处理器结构相关代码都放在arch/*/kernel目录下。

net目录里是核心的网络部分代码,其每个子目录对应于网络的一个方面。

lib目录包含了核心的库代码,不过与处理器结构相关的库代码被放在arch/*/lib/目录下。

scripts目录包含用于配置核心的脚本文件。

documentation目录下是一些文档,是对每个目录作用的具体说明。

QEMU是一个面向完整PC系统的开源仿真器。在本次实验中它就起到仿真一个Linux系统的作用。

-kernel 引用一个linux内核

-initrd 初始化一个临时的RAM磁盘,是系统引导过程中挂载的一个临时文件系统。

start_kernel

start_kernel函数之前的内容基本都是汇编语言,而从该函数开始内核进入c语言部分,功能则是内核主要功能的初始化。

步骤如下:

smp_setup_processor_id(); 制定当前cpu的逻辑号,当系统中只有一个cpu的情况,则此函数不做出操作

lockdep_init(); 初始化内核依赖的关系表(hash表)

localirq_disable(); 关闭当前CPU中断

early_boot_irqs_off(); early_boot_irqs_enabled,通过该标记可以让我们知道是否在early bootup code。

early_init_irq_lock_class(); 设置所有IRQ描述符的锁是统一的锁还是各有各的小锁

lock_kernel(); 获得大内核锁,该锁可以用来锁定整个内核。

time_init(); 初始化tick控制功能,注册clockevents的框架

boot_cpu_init(); 设置第一个CPU核为活跃CPU核。若系统为单CPU核系统,则设置仅有的CPU为活跃CPU核。

printk(KERN_NOTICE); printk(linux_banner);输出打印版本信息。

setup_arch(&command_line); 设置与初始化硬件体系相关的环境并调用

setup_per_cpu_areas(); 每个cpu分配pre-cpu结构内存

sched_init(); 进程调度器初始化

preempt_disable(); 内核的抢占

printk(boot_command_line); 提取分析核心启动参数过程(从bootloader中传递)

build_all_zonelists(); 建立系统内存页区(zone)链表

printk(KERN_NOTICE "Kernel command line: %s/n", boot_command_line); 打印Linux启动命令行参数

parse_early_param(); 解析早期格式的内核参数

trap_init(); 设置CPU的异常处理函数。

init_IRQ(); 初始化IRQ中断和终端描述符。

pidhash_init(); 初始化hash表

init_timers(); 初始化定时器Timer相关的数据结构。

hrtimers_init(); 对高精度时钟进行初始化。

softirq_init(); 初始化软中断。

time_init(); 初始化系统时间

profile_init();对内核的一个性能测试工具profile进行初始化。

local_irq_enable(); 使能IRQ中断

console_init(); 初始化控制台以显示printk的内容

接下来就是执行rest_init();

进程产生

从rest_init()开始,Linux系统就开始产生进程,通过kernel(kernel_init,NULL,CLONE_FS)启动内核进程kernel_init,也就是1号进程,它管理调度其他的内核进程,并由kthread_create_list全局链表管理其内核线程列表。

接着创建二号进程kthreadadd()

当系统没有进程需要执行的时候,就会调度到idle进程,也就是0号进程,它自系统开始运作时便一直存放于系统之中。在某种角度来说,它创建了1号进程和其他的进程。

实验截图

设置start_kernel的断点与rest_init的断点



运行至rest_init处时的系统运行图



rest_init函数处的上下文



start_kernel函数处的上下文



参考文献

《linux内核文件目录结构》:http://blog.sina.com.cn/s/blog_4ec78da90100g9iw.html

池彬宁原创作品转载请注明出处 + 《linux内核分析》mooc课程http://mooc.study.163.com/course/ustc-1000029000 ”
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: