微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > linux内核启动流程

linux内核启动流程

时间:11-22 来源:互联网 点击:

  1. calls(void)
  2. {
  3.   initcall_t*call;
  4.   call=&__initcall_start;
  5.   do{
  6.    (*call)();
  7.    call++;
  8.   }while(call<&__initcall_end);
  9.   /*Makesurethereisnopendingstufffromtheinitcallsequence*/
  10.   flush_scheduled_tasks();
  11. }

查看 /arch/i386/vmlinux.lds,其中有一段代码

[cpp]view plaincopyprint?

  1. __initcall_start=.;
  2. .initcall.init:{*(.initcall.init)}
  3. __initcall_end=.;

其含义是__initcall_start指向代码节.initcall.init的节首,而__initcall_end指向.initcall.init的节尾。

do_initcalls所作的是系统中有关驱动部分的初始化工作,那么这些函数指针数据是怎样放到了.initcall.init节呢?在include/linux/init.h文件中有如下3个定义:
1. #define __init_call   __attribute__ ((unused,__section__ (".initcall.init" ))
__attribute__的含义就是构建一个在.initcall.init节的指向初始函数的指针。
2. #define __initcall(fn) static initcall_t __initcall_##fn __init_call = fn
##意思就是在可变参数使用宏定义的时候构建一个变量名称为所指向的函数的名称,并且在前面加上__initcall_
3. #define module_init(x) __initcall(x);
很多驱动中都有类似module_init(usb_init)的代码,通过该宏定义逐层解释存放到.initcall.int节
中。

blkmem相关的修改(do_initcalls()初始化驱动时执行此代码)
在blkmem_init ()函数中,调用了blk_init_queue()函数,blk_init_queue()函数调用了blk_init_free_list()函数, blk_init_free_list()函数又调用了blk_grow_request_list()函
数,在这个函数中会 kmem_cache_alloc出nr_requests个request结构体。
这里如果nr_requests的值太大,则将占用过多的内存,将造成硬件内存不够,因此可以根据实际情况将其替
换成了较小的值,比如32、16等。

free_initmem
这个函数在arch/armnommu/mm/init.c文件中,其作用就是对init节的释放,也可以通过修改代码指定为
不释放。

1.26.3 init执行过程

在内核引导结束并启动init之后,系统就转入用户态的运行,在这之后创建的一切进程,都是在用户态进行。
这里先要清楚一个概念:就是init进程虽然是从内核开始的,即在前面所讲的init/main.c中的init()函数
在启动后就已经是一个核心线程,但在转到执行init程序(如 /sbin/init)之后,内核中的init()就变成
了/sbin/init程序,状态也转变成了用户态,也就是说核心线程变成了一个普通的进程。这样一来,内核中
的init函数实际上只是用户态init进程的入口,它在执行execve("/sbin/init",argv_init,
envp_init)时改变成为一个普通的用户进程。这也就是exec函数的乾坤大挪移法,在exec函数调用其他程
序时,当前进程被其他进程“灵魂附体”。
  除此之外,它们的代码来源也有差别,内核中的init()函数的源代码在/init/main.c中,是内核的一部
分。而/sbin/init程序的源代码是应用程序。
init程序启动之后,要完成以下任务:检查文件系统,启动各种后台服务进程,最后为每个终端和虚拟控制台
启动一个getty进程供用户登录。由于所有其它用户进程都是由init派生的,因此它又是其它一切用户进程的
父进程。
  init进程启动后,按照/etc/inittab的内容进程系统设置。很多嵌入式系统用的是BusyBox的init,
它与一般所使用的init不一样,会先执行/etc/init.d/rcS而非/etc/rc.d/rc.sysinit。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top