linux源码分析(五)-start_kernel
前置:这里使用的linux版本是4.8,x86体系。
local_irq_disable();
这个函数是做了关闭中断操作。和后面的local_irq_enable相对应。说明启动的下面函数是不允许被中断抢占的。这个函数追下去会发现下面的代码:
static inline void native_irq_disable(void)
{
asm volatile("cli": : :"memory");
}
这个写法是linux的内联汇编写法。在C语言中写汇编语言。实际上调用的是汇编cli命令。cli命令是禁用中断功能。http://rock3.info/blog/2013/11/24/linux-c中调用汇编用法/
接着start_kernel,linux关闭完中断之后,还使用了一个变量early_boot_irqs_disabled来标记已经关闭irq了。
这里稍微说说irq的概念,我们把中断分为两个概念,一个是上半部,一个是下半部,上半部指的是硬件直接要求立即响应的中断。下半部指的是可以在某个特定时间之后执行的。这里的IRQ就是一个上半部概念。每个硬件设备都有一个irq线,通过这个线把中断描述符传递给CPU,CPU获取中断之后立即执行对应已经注册的操作。
boot_cpu_init()
这个函数功能是初始化第一个CPU。
void __init boot_cpu_init(void)
{
int cpu = smp_processor_id();
/* Mark the boot cpu "present", "online" etc for SMP and UP case */
set_cpu_online(cpu, true);
set_cpu_active(cpu, true);
set_cpu_present(cpu, true);
set_cpu_possible(cpu, true);
}
先获取cpu的id,在smp下,获取第一个处理器ip,非smp,第一个cpu的id为0。后面就是设置cpu的四个标志位。
page_address_init()
这个是页地址初始化操作。
我们先要了解下段式管理和页式管理。我们会有三个地址,逻辑地址,虚拟地址,物理地址。CPU要将一个逻辑地址转换为物理地址,需要两步:首先CPU利用段式内存管理单元,先将逻辑地址转换为线性地址(虚拟地址)。再利用页式管理单元,把虚拟地址,转化为物理地址。
形象理解,段式管理就是一个大大的内存按照目的分为几段,有的段比较大,有的段比较小。但是呢,每个段的最低地址位都是0,实际的地址位是段的偏移量。所以,这里就存在逻辑地址和虚拟地址的转换了。为什么要进行分段管理呢?进行分段管理,能使得我们有可能对不同的内存段赋予不同的权限管理。
页式管理是一段内存,按照指定大小划分,每4k为一页。这里就有一个虚拟地址和物理地址的映射关系了。比如在一个三级的页式管理中,一个虚拟地址32位按照10,10,12分为3段,前10位是页目录地址,后10位是页表地址,最后12位是偏移量地址。这里其实有个奇怪的地方了。
为什么要进行页式管理呢?不管是否有分页管理,一个32位的地址,最多指向的也就是4G内存空间。页式管理其实是为了更好地利用内存。比如假设内存是连续分配的,进程A获取了1~100的内存空间,进程B获取了100~104的内存空间,进程C获取了104~200的内存空间。现在进程B释放空间了,但是只有很小的4。这个时候,如果后续的进程要申请的空间都是大于4的,那么100~104这个内存空间段就永远没有办法被分配。而使用页式管理就有办法避免这个问题。它可以让程序使用的内存在逻辑上是连续的,在物理上是离散的。
回到linux中,由于仅有一部分体系支持段式管理,基于兼容的原因吧,linux并没有支持段式管理。换句话说,linux把内存块当作是一个段。所以实际上,在linux中,逻辑地址和虚拟地址是一样的。但是linux把页式管理是全盘接受了。
回到这个函数,page_address_init()
查找这个函数的定义,你可以看到根据宏不同有两种定义,一种是
#if !defined(HASHED_PAGE_VIRTUAL) && !defined(WANT_PAGE_VIRTUAL)
#define page_address(page) lowmem_page_address(page)
#define set_page_address(page, address) do { } while(0)
#define page_address_init() do { } while(0)
#endif
一种是
void __init page_address_init(void)
{
int i;
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);
}
}
#endif /* defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL) */
首先,这里分配的页地址空间指的是内核的页地址空间。linux把4G的虚拟地址空间分为3G用户地址空间+1G内核地址空间。基本上是使用物理地址+3G的方式进行直接映射的。所以一般初始化内核地址空间的时候并不需要做任何操作。但是,当有些系统自身需要的内存大于896M的时候,就出现问题了。首先1G的内核空间,linux内核会把它分为896M的操作系统使用的空间,和128M的IO映射空间。当有些操作系统自身需要的内存大于896M,那么就难免有一些操作系统空间需要使用虚拟地址的形式,实际上是占用了原本用户的系统空间,这一部分空间就叫做high memory。(那么想对,原本已经有的896M的空间叫做low memory)。这一部分的空间映射,是保存在128M的IO映射空间里面的。http://blog.sina.com.cn/s/blog_6488248f0100wu6v.html
linux源码分析(五)-start_kernel的更多相关文章
- linux源码分析2
linux源码分析 这里使用的linux版本是4.8,x86体系. 这篇是 http://home.ustc.edu.cn/~boj/courses/linux_kernel/1_boot.html ...
- Vue系列---理解Vue.nextTick使用及源码分析(五)
_ 阅读目录 一. 什么是Vue.nextTick()? 二. Vue.nextTick()方法的应用场景有哪些? 2.1 更改数据后,进行节点DOM操作. 2.2 在created生命周期中进行DO ...
- ABP源码分析五:ABP初始化全过程
ABP在初始化阶段做了哪些操作,前面的四篇文章大致描述了一下. 为个更清楚的描述其脉络,做了张流程图以辅助说明.其中每一步都涉及很多细节,难以在一张图中全部表现出来.每一步的细节(会涉及到较多接口,类 ...
- MPTCP 源码分析(五) 接收端窗口值
简述: 在TCP协议中影响数据发送的三个因素分别为:发送端窗口值.接收端窗口值和拥塞窗口值. 本文主要分析MPTCP中各个子路径对接收端窗口值rcv_wnd的处理. 接收端窗口值的初始化 ...
- vuex 源码分析(五) action 详解
action类似于mutation,不同的是Action提交的是mutation,而不是直接变更状态,而且action里可以包含任意异步操作,每个mutation的参数1是一个对象,可以包含如下六个属 ...
- jQuery 源码分析(五) map函数 $.map和$.fn.map函数 详解
$.map() 函数用于使用指定函数处理数组中的每个元素(或对象的每个属性),并将处理结果封装为新的数组返回,该函数有三个参数,如下: elems Array/Object类型 指定的需要处理的数组或 ...
- Vue.js 源码分析(五) 基础篇 方法 methods属性详解
methods中定义了Vue实例的方法,官网是这样介绍的: 例如:: <!DOCTYPE html> <html lang="en"> <head&g ...
- motan源码分析五:cluster相关
上一章我们分析了客户端调用服务端相关的源码,但是到了cluster里面的部分我们就没有分析了,本章将深入分析cluster和它的相关支持类. 1.clustersupport的创建过程,上一章的Ref ...
- java动态代理——代理方法的假设和验证及Proxy源码分析五
前文地址 https://www.cnblogs.com/tera/p/13419025.html 本系列文章主要是博主在学习spring aop的过程中了解到其使用了java动态代理,本着究根问底的 ...
- Linux源码分析之:malloc、free
之前写代码的时候一直有个疑问,malloc申请内存的时候指定了内存大小,但是free的时候却只指定要释放的内存地址,那么free是如何知道它要释放的内存空间大小呢? 源码之前,了无秘密,下面就从源码来 ...
随机推荐
- ASP.NET Web API 接口执行时间监控
软件产品常常会出现这样的情况:产品性能因某些无法预料的瓶颈而受到干扰,导致程序的处理效率降低,性能得不到充分的发挥.如何快速有效地找到软件产品的性能瓶颈,则是我们感兴趣的内容之一. 在本文中,我将解释 ...
- 关于JQuery的一个Bug
关于JQuery的什么问题了? .parents()这个方法与form放在一起有些不对 上码 <!DOCTYPE html> <html> <head> <m ...
- (DNS被劫持所导致的)QQ音乐与视频网页打开很慢的解决方法
这周开始发现一个很让人抓狂的现象,QQ音乐网页(http://y.qq.com)与QQ视频(http://v.qq.com/)网页打开超慢,甚至是无法打开,严重影响了业余的音乐视频生活. 以QQ视频为 ...
- Module Zero安装
返回<Module Zero学习目录> 使用模板创建(自动方式) 手动安装 核心(领域)层 基础设施层 展示层 这里需要抱歉的是,这里使用的博客园的Markdown语法,代码显示不是很好看 ...
- Redis应用场景一
Redis开创了一种新的数据存储思路,使用Redis,我们不用在面对功能单调的数据库时,把精力放在如何把大象放进冰箱这样的问题上,而是利用Redis灵活多变的数据结构和数据操作,为不同的大象构建不同的 ...
- Stop Googling!
http://www.experts-exchange.com/Programming/Languages/Java
- linux添加自定义的命令!
修改了/root/下的.bashrc -bash-4.1# vi .bashrc # .bashrc # User specific aliases and functions alias rm='r ...
- xamarin UWP ActivityIndicator
在xamarin的UWP平台使用ActivityIndicator时,如果你时后台创建的这个对象,请设置他的宽度,不然在UWP平台下会发现找不这个对象,其实是在这个平台和特点版本下的宽度没设置,导致有 ...
- 缓存篇(Cache)~大话开篇
回到占占推荐博客索引 闲话杂淡 想写这篇文章很久了,但总是感觉内功还不太够,总觉得,要写这种编程领域里的心法(内功)的文章,需要有足够的实践,需要对具体领域非常了解,才能写出来.如今,感觉自己有写这种 ...
- oracle 备份数据库对象(存储过程PROCEDURE,FUNCTION,VIEW,TRIGGER...)
开发过程中,需要不停的备份数据库对象, 特别是存储过程, 每次手动备份不免很低能啊 历经几次修改终于, 完美了,O(∩_∩)O哈哈~ (当然,你也可以再改简便一点~~~) select db ...