linux的启动涉及到一个解压与定位的过程,对于x86体系结构而言,系统被加载到0x100000的地方,那么swapper_pg_dir的值是什么呢?我们知道swapper_pg_dir是一个很重要的东西,它是所有进程内核空间的页表的模板,而且在涉及到896M以上的内存分配时,swapper_pg_dir也是一个同步的根,这些内存分配包括vmalloc区,高端永久区,高端临时区等。这里需要说明的是,swapper_pg_dir这个东西其实就是一个页目录的指针,页目录指针在x86中是要被加载到cr3寄存器的,每个进程都有一个页目录指针,这个指针指示这个进程的内存映射信息,每当切换到一个进程时,该进程的页目录指针就被加载到了cr3,然后直到切换到别的进程的时候才更改,既然swapper_pg_dir是一个页目录指针,那么这个指针是被哪个进程用的呢?现代操作系统的含义指示了进程间内存隔离,那么一个页目录指针只能被一个进程使用,那么到底是哪个特定的进程使用了swapper_pg_dir指针呢?遗憾的是,答案是没有任何用户进程使用swapper_pg_dir作为页目录指针,swapper_pg_dir只是在内核初始化的时候被载入到cr3指示内存映射信息,之后在init进程启动后就成了idle内核线程的页目录指针了,/sbin/init由一个叫做init的内核线程exec而成,而init内核线程是原始的内核也就是后来的idle线程do_fork而成的,而在do_fork中会为新生的进程重启分配一个页目录指针,由此可见swapper_pg_dir只是在idle和内核线程中被使用,可是它的作用却不只是为idle进程指示内存映射信息,更多的,它作为一个内核空间的内存映射模板而存在,在linux中,任何进程在内核空间就不分彼此了,所有的进程都会公用一份内核空间的内存映射,因此,内核空间是所有进程共享的,每当一个新的进程建立的时候,都会将swapper_pg_dir的768项以后的信息全部复制到新进程页目录的768项以后,代表内核空间。另外在操作3G+896M以上的虚拟内存时,只会更改swapper_pg_dir的映射信息,当别的进程访问到这些页面的时候会发生缺页,在缺页处理中会与swapper_pg_dir同步。

了解到swapper_pg_dir的意义与实际作用,我们来看一下它的初始化吧,首先要看它的定义,在arch/i386/kernel/head.S中:

.org 0x1000

ENTRY(swapper_pg_dir)

.long 0x00102007 //第一个页目录项,指示前4M的页面映射信息,0x00102000是前4M页表所在的物理页,而0x00000007是访问控制权限,二者相加构成一个页表,以下同义

.long 0x00103007 //第二个页目录项,指示4-8M的页面映射信息

.fill BOOT_USER_PGD_PTRS-2,4,0 //填充到内核边界

.long 0x00102007 //第768个页目录项,指示前4M的页面映射信息

.long 0x00103007 //第769个页目录项,指示第4-8M的页面映射信息

...

org 0x1000说明了让系统将swapper_pg_dir加载到地址0x1000处,可是内核最终搬到了0x100000处,那么swapper_pg_dir也就到了0x101000处,现在物理地址已经搞定了,那么最终进入保护模式并且启动分页时,swapper_pg_dir的虚拟地址会在哪里呢?我们看一下内核加载到了哪里然后加上0x1000就是swapper_pg_dir加载到的虚拟地址了,在vmlinux.lds中可以看出内核被加载到了0xc0100000处,于是swapper_pg_dir加载的虚拟地址就是0xc0101000,在初始化的时候,内核将0到8M的物理内存分别映射到了虚拟地址的0到8M和3G到3G+8M两个地方,而且过了初始化阶段到了最终的稳定页表,也同样有前XM的物理内存一一映射到虚拟内存的3G+XM的地方,于是swapper_pg_dir的虚拟地址就是0xc0101000,我们可以打印出swapper_pg_dir看看到底是多少,不幸的是,swapper_pg_dir并不从内核导出,那么怎么办呢?难道非要将打印信息加入内核启动函数然后从新编译一遍内核吗?其实不用,虽然swapper_pg_dir没有被导出,可是init_mm被导出了啊,我们知道init_mm就是内核启动时也就是idle进程的mm_struct,其中一个字段是pgd,就是swapper_pg_dir,我们可以打印init_mm->pgd的值,看看是多少。

事情到此还没有结束,如果你真的写了一个模块,并且打印init_mm.pdg的话,发现可能它并不是期望的0xc0101000,怎么回事呢?不要急, 遇到这种情况比遇到内核莫名其妙的down掉要好处理的多,再说这并不影响我们的生活,即使你最终没有弄清楚这是怎么一回事,那么也不会有什么损失的。这 种情况好解决的原因还有就是事情发生在内核初始化的阶段,也就是说swapper_pg_dir的初始化在内核初始化阶段,并且以后也不会变化,可能它的 内容会变,但是其本身的位置是不会变化的,因此,几乎不用调试,光看代码就可以解决问题,我们搜索一下近来的Changelog,发现在2.6.6中将 swapper_pg_dir从原来的固定的.org 0x1000的位置移到了BSS段当中了,因为bss段仅仅拥有占位符而不占用映像静态空间,它的真正数据并没有初始化,因此交给操作系统初始化就可以 了,既然没有初始化的数据,那么就没有必要在静态的映像中占据空间,而是让操作系统将其载入内存时将bss清零即可,linux内核本身就是操作系统内 核,因此它自己负责在启动的时候将bss段清零,因为初始化的时候,临时页表也就需要两个页目录用来映射物理内存的0到8M,这两个页目录很简单,一点不 复杂,没有必要写死到内核映像从而占据着3个页面的空间,因此放到bss段中就可以节省3页面的空间,然后在内核启动过程中再手动初始化那两个页目录的 值,这样做十分有意义。那么bss被加载到哪里就决定了swapper_pg_dir被加载到了哪里,那么bss到底在哪呢?从arch/i386 /kernel/vmlinux.lds.S中可以大致知道答案,如果想知道更加确切的,可以参考/boot/System.map文件,然后可以再打印 一下init_mm.pgd的值,看看是不是在bss里面,其实都不用打印,在System.map里面就有swapper_pg_dir的值,该值在 2.6.6之后的内核肯定在bss中,之前的肯定是0xc0101000。最后我们看一下2.6.6以后的swapper_pg_dir的定义:   
.section ".bss.page_aligned","w"   
ENTRY(swapper_pg_dir)   
        .fill 1024,4,0

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

linux的swapper pg dir的初始化相关推荐

  1. Linux入门之系统启动过程及初始化----“翻滚吧,牛宝宝”

    每当你按下开机电源键的时候,总是怀着一颗虔诚的心,抱着求神拜佛的念头,祈求机器顺利开机,不要出幺蛾子:每当你看到屏幕上输出的一行又一行的信息,绿的OK,红的failed,迷茫的眼神穿透了显示器:这一切 ...

  2. c++ map 初始化_如何调整Linux内核启动中的驱动初始化顺序?

    如何调整Linux内核启动中的驱动初始化顺序?[问题] 此处我要实现的是将芯片的ID用于网卡MAC地址,网卡驱动是enc28j60_init. 但是,读取芯片ID的函数,在as352x_afe_ini ...

  3. Linux中断一网打尽(1) — 中断及其初始化

    女主宣言 通过本文您可以了解到:Linux 中断是什么,如何分类,能干什么?Linux 中断在计算机启动各阶段是如何初始化的? PS:丰富的一线技术.多元化的表现形式,尽在"360云计算&q ...

  4. linux源码分析之cpu初始化 kernel/head.s,linux源码分析之cpu初始化

    linux源码分析之cpu初始化 kernel/head.s 收藏 来自:http://blog.csdn.net/BoySKung/archive/2008/12/09/3486026.aspx l ...

  5. linux下安装pg数据库步骤,Linux下安装PG

    安装包下载地址 最好下载编译好的二进制安装包,直接解压就可以使用 1. 添加postgres用户: groupadd postgres useradd -d /home/postgres -m pos ...

  6. linux 的 swapper 进程不能sleep,Linux进程管理与调度.ppt

    Linux进程管理与调度 关于进程与线程Linux进程实现Linux进程调度策略Linux进程调度实现 1Linux进程与线程 Linux进程Linux线程 进程作为资源分配的基本单位而存在 线程作为 ...

  7. linux机器启动pg数据库命令,Linux下创建Postgresql数据库的方法步骤

    前言 PostgreSQL (也叫 Postgres)是一个自由的对象-关系数据库服务器(数据库管理系统),它在灵活的 BSD-风格许可证下发行.因为之前用默认的配置创建pgsql数据库,导致root ...

  8. linux 串口驱动(二)初始化 【转】

    转自:http://blog.chinaunix.net/uid-27717694-id-3493611.html 8250串口的初始化: (1)定义uart_driver.uart_ops.uart ...

  9. Linux 系统服务管理和控制程序(初始化系统/Init System) -- systemd 介绍

    文章目录 systemd 简介 systemd 启动过程概述 Systemd的争议 systemd 简介 开发systemd的主要目的就是减少系统引导时间和计算开销.systemd(系统管理守护进程) ...

最新文章

  1. linux-glibc内存管理小结2(内存相关系统调用的实现)
  2. pyinstaller打包之后运行出现:Could not find the matplotlib data files
  3. redis系列:基于redis的分布式锁
  4. Visual C++ 2010中更换MFC对话框默认图标
  5. linux path环境变量检索目录,Linux下动态链接库加载路径及搜索路径问题
  6. asinh函数_JavaScript中带有示例的Math.asinh()方法
  7. 黑客到底可以厉害到什么程度
  8. 关于7z结尾的压缩包操作系统
  9. 快过年了,来,来,来!给七大姑八大姨好好解释解释【啥是DBA 】
  10. zabbix监控iptables防火墙状态之是否有丢弃的包(攻-击)
  11. zabbix监控哪些东西_监控系统选型,一篇全搞定
  12. docker打包镜像(实用版)
  13. 适用于Chrome类浏览器的喜马拉雅音频下载插件
  14. iTunes出现提示“iTunes不能读取iPhone的内容,请前往iPhone偏好设置的摘要选项卡,然后点击“恢复”以将此iPhone恢复为出厂设置。”
  15. 中国石油大学《安全行为学》第三阶段在线作业
  16. DHCP Relay 配置教程
  17. 106、对待低优先级bug的可行方法
  18. 图书速读 | 一分钟读完《斯坦福高效睡眠法》
  19. 433MHz通信 发F115 收SYN480R
  20. 剪不断,理还乱--Oracle的字符集乱码问题

热门文章

  1. Tomcat 结合Atomikos 实现JTA
  2. 微信小程序全栈开发实践 第二章 微信小程序组件介绍及使用 -- 2.6 scroll-view组件,在小程序中如何实现滚动锚定,如何渲染一个滚动的长列表?
  3. 2019年7月中国奶业经济月报
  4. 如何快速摆脱焦虑困扰,重建内心平静?分享一份无需药物的指南,让你重拾自信并远离焦虑!
  5. python目录名称无效_python目录名错误怎么解决?这几种方案才是你需要学会的
  6. like作连词it作形式宾语
  7. 每个程序员都应读的书
  8. 可配D31,d15功能的ZJ-4型宽量程型D33测试仪
  9. Web应用防火墙使用“指北”
  10. 广州国际车用空调展圆满落幕!旭派载誉而归,收货满满!