内核初始化
Posted japer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内核初始化相关的知识,希望对你有一定的参考价值。
内核启动的入口函数 start_kernel() {init/main.c配置文件} , 里面有XXXX_init的初始化函数
1)在操作系统中有个创始进程,set_task_stack_end_magic(&init_task)。 有一个参数 init_task 定义是struct task_struct init_task = INIT_TASK(init_task) 是系统默认创建的第一进程(0号进程) 唯一一个没有通过fork或者Kernel_thread 产生的进程
(Procese List) 项目管理进程 , 内有所有项目
2)办事大厅: 函数(trap_init()) 其中设置了很多中断门(Interrupt Gate)
其中 set_system_intr_gate(IA32_SYSCALL_VECTOR,entry_INT80_32) 为系统调用的中断门。 并且通过发送中断的方式进行的。 (64位有另外的系统调用方法)
3) 会议室管理系统: 初始化内存管理模块【mm_init()】
初始化调度模块【 sched_init()】 进行调度时则需要执行一定的调度策略
文件系统 rootfs 初始化基于内存的文件系统【 vfs_caches_init()】
函数里调用 mnt_init()-> init_rootfs()
register_filesystem(&rootfs_fs_type) ,在VFS 虚拟文件系统里注册了一种类型 定义为 struct file_system_type rootfs_fs_type
文件系统即为项目资料库。首先要兼容所有的文件系统,需将文件的相关数据结构和操作抽象出来,形成一个对上提供统一的接口。这个抽象层就是VFS ( Virtual File System) 。虚拟文件系统
此时,rootfs 还有其他用处。
start_kernel() 调用的是 rest_init() 。 是做其他方面的初始化
4) rest_init 为原始进程 要创建第二个进程则用 kernel_thread(kernel_init,NULL,CLONE_FS)
当进程出现的时候就要考虑安全性,并将进程做一些主要的权限区分等级,比如哪些是核心资源,那些事非核心资源。
核心关键资源放在内部,则称为内核态(Kernel Mode)
普通的程序资源则可放在应用里,则称为用户态(User Mode)
系统启动时已经处于保护模式。则用户的权限直接导致当前用户的访问空间以及读写等操作空间。
若普通用户想访问核心资源,则需要提供系统调用的办事大厅,可在此请求。然后就是内核态, 等用户态代码做完了返回结果就可以了。
若用户态的程序运行一半的时候需要访问内核资源,则暂停当前运行,调用系统调用,然后转到内核中的代码继续运行。然后再内核网卡上进行排队处理。等处理完成后也就是系统调用结束,则返回到用户态,继续暂停的程序
程序过程: 用户态 — 系统调用 — 保持寄存器 — 内核态执行系统调用 — 恢复寄存器 — 返回用户态,然后接着运行。
5) 从内核态到用户态
当执行 kernel_thread 函数时,我们处于内核态,kernel_thread 的参数是一个函数 kernel_init 并且会此进程会运行此函数, 在此里面会调用 kernel_init_freeable() :
if (!ramdisk_execute_command)
ramdisk_execute_command = "/init";
进程运行的是一个文件,若打开run_init_process函数。则发现它调用的是 do_execve 。 (execve 是系统调用,作用是运行一个执行文件,加一个do_ 则是内核系统调用的实现。 并且会尝试运行 ramdisk 的 “/init“ 或者 ”/sbin/init" , "/etc/init" , "/bin/init" , "/bin/sh" 。 不同的Linux版本会选择不同的文件启动,但只需要有一个启动即可。
则调用过程 do_execve -> do_execveat_common -> exec_binprm -> search_binary_handler,
运行加载二进制文件,则需要Linux下常用的格式 ELF ( Executable and Linkable Format,可执行与可链接格式)
6) Ramdisk 的作用
当访问一个U盘或存储系统的时候,则需要安装驱动才能访问,若存储系统过多,则安装的驱动也多。此时则先弄一个基于内存的文件系统,内存访问则不需要驱动。这个就叫 ramdisk。 ramdisk 则是根文件系统
然后运行 ramdisk 上的 /init 。运行完了就已经在用户态上了。 /init 程序会先根据存储系统的类型加载驱动,然后设置真正的根文件系统, 然后ramdisk上的 /init 会启动文件系统上的 init,然后就是各种系统初始化,启动系统的服务,启动控制台,用户登陆等等。。。
7) 创建 2号进程
Kernel_thread(kthreadd,NULL,ClONE_FS | CLONE_FILES) 使用kernel_thread 函数创建进程 【函数名 thread 可翻译为 “线程” 】
从用户态来看,创建进程即为立项,也就是启动项目,此项目包含会议室,资料库等。 但项目需要人去执行,若有多个人并行执行不同的部分,则称为多线程 (Multithreading),若只有一个人,那则是此项目的主线程。
从内核看,无论进程还是线程,统称为任务(Task),使用相同的数据结构,平放在同一个链表中。
于此,函数 kthreadd 负责所有内核态的线程的调度和管理,是内核态所有线程运行的祖先
以上是关于内核初始化的主要内容,如果未能解决你的问题,请参考以下文章