目录
- 前言:
- 一、了解虚拟地址
- 二、页表映射
- 三、常量区不能被修改的原理
- 四、常量区不可修改的意义
前言:
平时我们在编写代码时都会用到或遇到所谓的常量区或者不可修改的代码,比如说用双引号包起来字符串(“Hello World”)、C++中的 const、Java中的final等,平时我们在用或者见到时只知道这时语法规定的,但你有没有想过这到底 是为什么呢?
本文将从操作系统底层分析常量区不可修改的原理
一、了解虚拟地址
虚拟地址是一个较为抽象的概念,也是操作系统中非常重要的一个概念
简单来说,就是我们所能看到的地址,基本上都不是真正的地址,是操作系统给我们的“假地址(虚拟地址)”,
比如我们定义一个变量,我们可以用取地址符号&获取它的地址,你以为这就是在在内存中真正的地址了吗?其实这只是系统给你的一个虚拟地址,我们是得不到它的物理地址的(真正的地址),但操作系统可以(通过页表映射,下文会讲解),主要也是为了保护吧,不能让用户轻易直接访问内核数据
二、页表映射
操作系统又是如何处理虚拟地址与物理地址(真正的内存地址)之间的关系的呢?
操作系统使用了一个叫做页表的东西来映射,我们看到的是虚拟地址,而操作系统通过页表将虚拟地址映射到一片物理地址空间中去,这样就建立起虚拟地址与物理地址之间的关系
其实上面的讲述还不够详细,我只是简略讲解了一下,想要详细理解可以看看这篇文章有关Linux中进程地址空间及页表原理的理解,里面有详细的讲解
三、常量区不能被修改的原理
到这里我们已经明白了页表映射虚拟地址到物理地址的概念,下面就可以进入到我们的正题了
我们知道页表可以映射,但它在映射的同时还会附带上读写读写权限,如下图所示
而我们修改常量区里的数据要通过常量区里的地址修改,但常量区里给的地址是虚拟地址,在通过页表映射物理地址时会被页表的权限终止掉(只读),不让修改,因此常量区不让修改不是语言上的限制,而是操作系统上的限制
四、常量区不可修改的意义
在写代码的过程中由于一些疏忽,可能会对一些不应该改变的数据做出修改的操作,最重要的是这种运行时的错误极其难找出来
因此在这种变量前加const(c/c++)、final(Java等)是将在运行时的错误提前到编译时错误,因为运行时的错误藏得会比较深,是一种防御性编程的范畴,是一种好的编译习惯