start_kernel函数部分分析

简介: start_kernel函数部分分析

根据板子里面的启动信息,cat /proc/kmsg,对着代码看。

start_kernel函数分析

1. set_task_stack_end_magic(&init_task);

抽取关键部分

//找到栈顶位置并设置个魔术字,防止堆栈 将 thread_info 的数据覆盖;  //如果是向上生长的栈,直接通过(task_thread_info + 8K - 1)找到栈底并设置魔术字  //内核栈大小一般为4K或者8K.  set_task_stack_end_magic(&init_task);    stackend = end_of_stack(tsk);      return (unsigned long *)(task_thread_info(p) + 1);    *stackend = STACK_END_MAGIC; // 0x57AC6E9D

//宏定义了就是向上生长static inline unsigned long *end_of_stack(struct task_struct *p){#ifdef CONFIG_STACK_GROWSUP  return (unsigned long *)((unsigned long)task_thread_info(p) + THREAD_SIZE) - 1;#else  return (unsigned long *)(task_thread_info(p) + 1);#endif}

640.png

(栈向下生长的情况)

640.png

(栈向上生长的情况)

2. smp_setup_processor_id

int i;  u32 mpidr = is_smp() ? read_cpuid_mpidr() & MPIDR_HWID_BITMASK : 0;  u32 cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
  cpu_logical_map(0) = cpu;  for (i = 1; i < nr_cpu_ids; ++i)    cpu_logical_map(i) = i == cpu ? 0 : i;
  /*   * clear __my_cpu_offset on boot CPU to avoid hang caused by   * using percpu variable early, for example, lockdep will   * access percpu variable inside lock_release   */  set_my_cpu_offset(0);
  pr_info("Booting Linux on physical CPU 0x%x\n", mpidr);

先通过is_smp()函数判断是否为smp处理器

static inline bool is_smp(void){#ifndef CONFIG_SMP  return false;#elif defined(CONFIG_SMP_ON_UP)  extern unsigned int smp_on_up;  return !!smp_on_up;#else  return true;#endif}

我的是imx6ull板子,不是对称多处理器,这里宏没定义,直接返回false。

所以mpidr 为0

3. local_irq_disable

暂时禁止本地中断, 设置完相关的东西后再开启

// 禁止本地中断  local_irq_disable    raw_local_irq_disable      arch_local_irq_disable

4. boot_cpu_init

初始化 Boot CPU

// 设置boot cpu  boot_cpu_init    smp_processor_id      raw_smp_processor_id        current_thread_info()->cpu    set_cpu_online    set_cpu_active    set_cpu_present    set_cpu_possible

5.page_address_init

初始化高端内存线性地址中永久映射的全局变量.IMX6ULL这里的宏没开,所以这里应该是空

page_address_init    // page_address_htable 是个全局结构体数组,     for (i = 0; i < ARRAY_SIZE(page_address_htable); i++)      INIT_LIST_HEAD(&page_address_htable[i].lh);      spin_lock_init(&page_address_htable[i].lock);

6.pr_notice("%s", linux_banner);

linux_banner 字符串保存了 linux 版本号,编译主机,GCC 版本,编译 时间等信息。在开机过程中可以看到log

640.png

/* FIXED STRINGS! Don't touc.h! */const char linux_banner[] =  "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"  LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";

 以下是编译生成的文件,路径在include\generated\compile.h

#define UTS_MACHINE "arm"#define UTS_VERSION "#9 SMP PREEMPT Sat Dec 25 20:49:44 CST 2021"#define LINUX_COMPILE_BY "zrc"#define LINUX_COMPILE_HOST "zrc"#define LINUX_COMPILER "gcc version 4.9.4 (Linaro GCC 4.9-2017.01) "

7. setup_arch

初始化体系相关的部分,实现与体系和芯片有关

// 初始化体系相关的部分,实现与体系和芯片有关  setup_arch(&command_line)    setup_processor(); // 从硬件获得体系相关的信息,并将该信息用于系统的初始化    // __atags_pointer 指向 DTB 所在的物理地址    mdesc = setup_machine_fdt(__atags_pointer)

号主:一枚机械专业本科生,经历了转行,从外包逆袭到芯片原厂的Linux驱动开发工程师,深入操作系统的世界,贯彻终身学习、终身成长的理念。平时喜欢折腾,寒冬之下,抱团取暖,期待你来一起探讨技术、搞自媒体副业,程序员接单和投资理财。【对了,不定期送闲置开发板、书籍、键盘等等】。

如果你想了解我的转行经验,欢迎找我交流~gongzhong号【哆哆jarvis】

一起不断探索自我、走出迷茫、找到热爱,希望和你成为朋友,一起成长~

相关文章
/etc/init.d/functions运用实战配置system服务详解
/etc/init.d/functions运用实战配置system服务详解
|
10月前
|
编解码 人工智能 算法
Rasterio:rasterio.open函数参数和用法解析(以GPM Imerg Early nc转tif为例)
Rasterio:rasterio.open函数参数和用法解析(以GPM Imerg Early nc转tif为例)
251 0
|
Linux
LINUX虚拟机安装增强功能时报错: Kernel headers not found for target kernel. Please install them and execute
LINUX虚拟机安装增强功能时报错: Kernel headers not found for target kernel. Please install them and execute
273 0
|
Linux
记录一次kernel无法找到init的问题
记录一次kernel无法找到init的问题
142 1
记录一次kernel无法找到init的问题
【openstack】问题记录:error: you need to load the kernel first【已解决】】
【openstack】问题记录:error: you need to load the kernel first【已解决】】
3564 0
【openstack】问题记录:error: you need to load the kernel first【已解决】】
|
SQL MySQL 关系型数据库
pt-tools系统:pt-kill 实战
列出几种常用场景,并进行分析实战测试 特殊、 打印出执行时间超过3秒的connection,仅仅打印,不kill 每2秒循环一次,超过10秒就退出pt-kill程序pt-kill --host xx.
1392 0
|
Linux 编译器 C语言
|
Linux
linux网络驱动初始化module_init函数跟踪
module_init函数对做驱动开发的同学是在太熟悉了,但是关于底层的知识可能大家有些不愿去了解,而其中知识对于网络初始化也直接相关,所以先将此分享。 在驱动程序中有module_init函数,该函数定义在文件 include/linux/module.h中(以前好像在include/linux/init.h中),如下。
2294 0