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是如何知道它要释放的内存空间大小呢? 源码之前,了无秘密,下面就从源码来 ...
随机推荐
- SVN Server for Migration
SVN Server: http://mxsuse01/svn/repos/erp/Oracle_EMS Report SVN (Put to SVN Sort) 1. *.RDF 2. *CP.LD ...
- 另类的表单数据"序列化"
背景:最近在做项目时,由于编辑页面需要提交的数据量有些多,而且在提交前还需要做一些逻辑处理,所以如果按照正常的方式,一个个的获取值然后拼接json对象传到后台的话相对工作量较大,而且容易出错,后期的维 ...
- 关于object和embed
最近发现很久之前写的demo 在FF上有兼容问题, 主要发生在如下: 由于时间太久,自己都有点搞不清怎么写的,尤其是object标签,今天查了很多资料,总结一下object标签 在网页中正常显示fla ...
- 又踩.NET Core的坑:在同步方法中调用异步方法Wait时发生死锁(deadlock)
之前在将 Memcached 客户端 EnyimMemcached 迁移 .NET Core 时被这个“坑”坑的刻骨铭心(详见以下链接),当时以为只是在构造函数中调用异步方法(注:这里的异步方法都是指 ...
- [.net 面向对象程序设计进阶] (11) 序列化(Serialization)(三) 通过接口 IXmlSerializable 实现XML序列化 及 通用XML类
[.net 面向对象程序设计进阶] (11) 序列化(Serialization)(三) 通过接口 IXmlSerializable 实现XML序列化 及 通用XML类 本节导读:本节主要介绍通过序列 ...
- gulp使用小结(一)
这篇文章不会介绍 gulp 的起源.发展:不会去一个个讲解 gulp API:也不想出现大段大段的 gulpfile.js 代码:更木有帮你分析 gulp 实现原理,只有一些我自己对 gulp 的使用 ...
- Outlook HTML渲染引擎
OutLook始终不离不弃 是不是很讨厌为Email代码兼容Outlook? 太遗憾了!虽然光都有尽头,但Outlook始终存在. 为了应付Email的怪癖,我们花了很多时间测试,确保我们搞定了所有O ...
- Spring学习记录(十一)---使用注解和自动装配
Spring支持用注解配置Bean,更简便. 上面的组件,是根据实际情况配的.比如写的一个类,是做业务处理的,那就用注解@Service表示服务层组件,以此类推.将整体分成不同部分. 要在xml加入c ...
- highchart导出图片
http://www.cnblogs.com/jasondan/p/3504120.html 项目中需求导出报表为图片存到Excel中去,或供其它页面调用. 开始存到截屏,但由于用户电脑分辨率不一样, ...
- div非弹出框半透明遮罩实现全屏幕遮盖css实现
IE浏览器下设置元素css背景为透明: background-color: rgb(0, 0, 0); filter: alpha(opacity=20); 非IE浏览器下设置元素css背景为透明: ...