linux_mips启动流程_存储相关

上传人:沈*** 文档编号:165666789 上传时间:2022-10-29 格式:DOC 页数:16 大小:486.01KB
收藏 版权申诉 举报 下载
linux_mips启动流程_存储相关_第1页
第1页 / 共16页
linux_mips启动流程_存储相关_第2页
第2页 / 共16页
linux_mips启动流程_存储相关_第3页
第3页 / 共16页
资源描述:

《linux_mips启动流程_存储相关》由会员分享,可在线阅读,更多相关《linux_mips启动流程_存储相关(16页珍藏版)》请在装配图网上搜索。

1、Linux-mips启动流程 -存储相关linux内核启动的第一个阶段是从 /arch/mips/kernel/head.s文件开始的。而此处正是内核入口函数kernel_entry(),该函数定义在 /arch/mips/kernel/head.s文件里。kernel_entry()函数是体系结构相关的汇编语言,它首先初始化内核堆栈段,来为创建系统中的第一个进程进行准备,接着用一段循环将内核映像的未初始化数据段(bss段在_edata和_end之间)清零,最后跳转到/arch/mips/kernel/setup.c 中的 start_kernel()初始化硬件平台相关的代码。下面讲述star

2、t_kernel() 函数。在这个函数中跟内存初始化的函数是setup_arch()。第一部分:以函数调用关系为线索下面是函数之间调用关系的框图:第一章:start_kenel()-setup_arch()setup_arch(&command_line);每种体系结构都有自己的 setup_arch() 函数,这些是体系结构相关的。【如何确定编译那个体系结构的 setup_arch() 函数呢?主要由 linux 源码树顶层 Makefile 中 ARCH 变量来决定的。例如: MIPS 体系结构的。SUBARCH := mipsARCH ?= $(SUBARCH)】。void _init

3、setup_arch(char *cmdline_p) cpu_probe(); 调用函数cpu_probe(),该函数通过MIPS CPU的PRID寄存器来确定CPU类型, 从而确定使用的指令集和其他一些CPU参数,如TLB等 prom_init(); prom_init() 函数是和硬件相关的,做一些低层的初始化,接受引导装载程序传给内核的参数,确定 mips_machgroup,mips_machtype 这两个变量,这两个变量分别对应着相应的芯片组合开发板;cpu_report();打印 cpu_probe() 函数检测到的 CPU 的 Processor ID。如果有浮点处理器,也打

4、印浮点处理器的 Processor ID。 【应用程序通过终端接口设备使用特定的接口规程与终端进行交互,与操作系统内核本身交互的终端称为控制台, 它可以是内核本身的内部显示终端,也可以是通过串口连接的外部哑终端。 由于大多数情况下控制台都是内核显示终端,因此内核显示终端也常常直接称为控制台。 内核终端对用户来说具有若干个虚拟终端子设备,它们共享同一物理终端, 但同一时刻只能有一个虚拟终端操作硬件屏幕。 宏 CONFIG_VT 的意思是否支持虚拟终端。 当配置了宏 CONFIG_VGA_CONSOLE 时为内核本身的内部显示终端。 当配置了宏 CONFIG_DUMMY_CONSOLE 时为通过串

5、口连接的外部哑终端。 用变量 conswitchp 来进行指定。#if defined(CONFIG_VT)#if defined(CONFIG_VGA_CONSOLE) conswitchp = &vga_con;#elif defined(CONFIG_DUMMY_CONSOLE) conswitchp = &dummy_con;#endif#endif】arch_mem_init(cmdline_p);对内存进行初始化。resource_init();这个函数遍历每一个内存空间范围(物理地址),在资源管理器中进行资源申请,并对内核代码和数据段进行资源申请。#ifdef CONFIG_SM

6、P plat_smp_setup();#endif / /start_kernel函数到此结束(以下均是)。以下图片是截自版本linux-2.6.34内核版本。第二章:start_kenel()-setup_arch()-arch_mem_init()接下来我们看看arch_mem_init()函数中的函数调用关系及各自的功能。static void _init arch_mem_init(char *cmdline_p)plat_mem_setup();这个函数是平台具体相关的,移植内核需要自己手动编写。对于开发板的 CPU 和 board 的初始化都是在这个函数中进行的。detects t

7、he memory configuration and will record detected memory areas using add_memory_region。就是在这里面建立了内存的初始面貌。代码如下: printk(Determined physical RAM map:n);print_memory_map();这个函数打印输出内存范围(物理地址)映像图。 【把字符数组 arcs_cmdline 拷贝到字符数组 command_line 和 boot_command_line中。 字符数组 arcs_cmdline 在 prom_init_cmdline() 函数中进行的赋值

8、。 为命令行启动参数字符串组合。参考linux-mips启动分析(3).txt。 strlcpy(command_line, arcs_cmdline, sizeof(command_line); strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);*cmdline_p = command_line;】parse_early_param();把字符数组 command_line 的地址赋值给函数的参数。返回给上级的函数,实际上这个指针返回到了start_kernel() 函数。 【这个 usermem 变量在 early_pa

9、rse_mem()函数进行修改。 参考下面的分析。 if (usermem) printk(User-defined physical RAM map:n); print_memory_map(); 】bootmem_init();函数对引导内存分配器进行初始化。sparse_init();在 linux 内核中可以选择三种内部的 memory 管理模型: FLATMEM、SPARSEMEM 和 DISCONTIGMEM。一般情况下选择 FLATMEM 内存管理模型肯定是正常的,它支持所有的系统,如果系统为非一致性的内存管理 NUMA 和支持内存热插拔的,可以选择其他两种。 这种 DISCON

10、TIGMEM 内存管理模型相比于FLATMEM 内存管理模提供了一些扩展的功能,在有些系统中,内存有许多的空洞,这个中模型提供了更有效的的处理这些 hole 的方法。然而,事实上尽管有许多的空洞,这些地址空间仍然是巨大的 flat 地址空间。所以也可以退化为 FLATMEM 内存管理模型。在许多的 NUMA 系统中,需要配置这种的内存管理模型。这中 SPARSEMEM 内存管理模型可以支持内存的热插拔的,如果你不确定,可以不选择这个配置选项。paging_init();函数初始化内核空间的页表,建立页表项。初始化内存节点和各个管理区和 mem_map 数组。第三章:start_kenel()-

11、setup_arch()-arch_mem_init()-bootmem_init()static void _init bootmem_init(void) unsigned long reserved_end; unsigned long mapstart = 0UL; unsigned long bootmap_size; int i; 取得内核映像的末尾地址(物理地址),如果没有定义 CONFIG_BLK_DEV_INITRD 这个宏, 这个 init_initrd() 函数为空函数,如果定义了返回文件系统的映像的结束地址。 reserved_end = max(init_initrd

12、(), PFN_UP(_pa_symbol(&_end); 对变量 min_low_pfn 和 max_low_pfn 进行初始化。 变量 min_low_pfn 表示系统可用的最小的 PFN(page frame num)。 变量 max_low_pfn 表示低端内存可用的最大的 PFN(page frame num)。 min_low_pfn = 0UL; max_low_pfn = 0; 下面的循环对每一个内存区域(物理地址)进行检测, 对变量 min_low_pfn 和 max_low_pfn 根据硬件进行赋值。 对变量 mapstart 进行赋值,这个变量还是等于内核映像的结束地址(

13、为什么不直接赋值呢?)。 for (i = 0; i max_low_pfn) max_low_pfn = end; if (start min_low_pfn) min_low_pfn = start; if (end = mapstart) continue; mapstart = max(reserved_end, start); 进行检测。 if (min_low_pfn = max_low_pfn) panic(Incorrect memory mapping !); if (min_low_pfn ARCH_PFN_OFFSET) printk(KERN_INFO Wasting

14、%lu bytes for tracking %lu unused pagesn, (min_low_pfn - ARCH_PFN_OFFSET) * sizeof(struct page), min_low_pfn - ARCH_PFN_OFFSET); else if (min_low_pfn PFN_DOWN(HIGHMEM_START) #ifdef CONFIG_HIGHMEM highstart_pfn = PFN_DOWN(HIGHMEM_START); highend_pfn = max_low_pfn;#endif max_low_pfn = PFN_DOWN(HIGHMEM

15、_START); 初始化低端内存引导内存分配器。分析见下面。 这个函数使用 mapstart 以后,第一个可用的 PFN 来初始化 min_low_pfn 和 max_low_pfn 之间的内存,并把节点加入 pgdat_list 节点链表。 bootmap_size = init_bootmem_node(NODE_DATA(0), mapstart, min_low_pfn, max_low_pfn); 把所有低端内存中的有效 RAM 页面在引导内存分配器中进行分配。 for (i = 0; i = max_low_pfn) continue; 对内核映像所占据的 RAM 空间进行保留。

16、if (start max_low_pfn) end = max_low_pfn; 进行错误检测。 if (end = start) continue; 计算得出这段 RAM 空间的 物理页面总数。 size = end - start; 在节点的位图中表目 size 个页面为空闲的。 free_bootmem(PFN_PHYS(start), size setup_arch()-arch_mem_init()-paging_init()void _init paging_init(void) unsigned long zones_sizeMAX_NR_ZONES = 0, ; 因为定义这个

17、 CONFIG_FLATMEM 宏,所以不定义下面的变量。#ifndef CONFIG_FLATMEM unsigned long zholes_sizeMAX_NR_ZONES = 0, ; unsigned long i, j, pfn;#endif 这个函数利用 swapper_pg_dir 设立一个静态页表作为 PGD。 pagetable_init();#ifdef CONFIG_HIGHMEM 这个函数取得高端内存首地址对应的 PTE 页表的起始页表项,并进行保护。 kmap_init();#endif 如果编译时没有设置 CONFIG_MIPS_MT_SMTC 宏定义,下面这个函

18、数为空函数。 kmap_coherent_init();在内存中每个节点分为 三个管理区, ZONE_DMA 表示低端范围的内存, ISA 设备要用到它。ZONE_NORMAL 由内核直接映射的线性地址空间。ZONE_HIGHMEM 内核不能够直接映射的地址空间。现在 ISA 设备很少,一般不定义 CONFIG_ZONE_DMA 这个宏。 下面的代码设置内存节点的各个管理区的大小。#ifdef CONFIG_ZONE_DMA if (min_low_pfn MAX_DMA_PFN & MAX_DMA_PFN = max_low_pfn) zones_sizeZONE_DMA = MAX_DMA

19、_PFN - min_low_pfn; zones_sizeZONE_NORMAL = max_low_pfn - MAX_DMA_PFN; else if (max_low_pfn MAX_DMA_PFN) zones_sizeZONE_DMA = max_low_pfn - min_low_pfn; else#endif zones_sizeZONE_NORMAL = max_low_pfn - min_low_pfn;#ifdef CONFIG_HIGHMEM 设置高端内存管理区的大小。 zones_sizeZONE_HIGHMEM = highend_pfn - highstart_p

20、fn; 这个 cpu_has_dc_aliases 变量是一个宏定义,这个宏定义了数据高速缓存 数据重影的问题,参考MIPS-cache重影问题的产生。 如果 CPU 有数据高速缓存的数据重影问题,则不支持高端缓存。 if (cpu_has_dc_aliases & zones_sizeZONE_HIGHMEM) printk(This processor doesnt support highmem. ); zones_sizeZONE_HIGHMEM = 0; #endif 下面代码初始化各个管理区,建立各个管理区的内核页表。 对于 UMA 系统,调用 free_area_init() 函

21、数, 对于 NUMA 系统,调用 free_area_init_node() 函数。#ifdef CONFIG_FLATMEM 初始化各个管理区和 mem_map 数组。 free_area_init(zones_size);#else 当为非 FLATMEM 类型内存管理模型时,执行。 pfn = min_low_pfn; 统计内存地址空间中的漏洞。 for (i = 0; i MAX_NR_ZONES; i+) for (j = 0; j setup_arch()-arch_mem_init()-paging_init()-free_area_init_nodes-free_area_init_node()-alloc_node_mem_map()中分配空间的,在start_kenel()-setup_arch()-arch_mem_init()-paging_init()-free_area_init_nodes-free_area_init_node()-free_area_init_core()-init_currently_empty_zone()-memmap_init()初始化数组某些项的值。关于linux-mips启动过程中关于存储的(项目需求的)函数调用关系和数据就介绍到此。 16 / 16

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!