坐井观天的:进程 | 虚拟内存 | 虚拟地址
sinye56 2024-12-06 19:06 13 浏览 0 评论
“ 进程、线程有什么区别?虚拟地址和物理地址有什么区别?让我们用一只青蛙的视角,来解读它们背后的秘密”
进程、线程、虚拟地址、物理地址,这些名词既熟悉也陌生!似乎无论看多少资料,都很难准确地弄清楚它们之间的差异和存在的意义。今天我们用CPU的视角,再次会会这个老朋友,看看你是否有新的启发?
奇怪的内存
先写一个最简单的程序。这个程序只做两件事情:定义一个全局变量 a,并赋值为:1;然后打印出 a 的地址和数值
#include <stdio.h>
#include <unistd.h>
int a = 1;
int main()
{
printf("address: %p, value: %d\n", &a, a);
sleep(10000000);
}
将上面的代码,编辑成可执行程序:p1;接着,修改一下代码:给全局变量 a 赋值为:2,再次编译出可执行程序:p2。
好了,两个程序:p1,p2 都准备好了,让我们再以两个进程的形式,运行它们:左边的窗口进程,运行p1;右边的窗口进程,运行p2
发现问题了吗?无论是 p1 还是 p2,它们输出的 a 的地址都是一样的,但 a 的值却不一样!难道同一个内存地址里面,既能存放 1,也能存放 2?
当然不是,原来0x555555558010是虚拟地址,并不是真实的物理内存地址,进程p1的0x555555558010,跟进程p2的0x555555558010,没有任何关系!
虚拟地址,只在进程内,是有意义的;可以用来指示不同变量,所对应的不同内存地址;但一旦跳出单一进程,在进程之间比较虚拟地址,就没有任何意义了!
MMU
是什么软件,拥有如此的魔力?能让进程p1和进程p2的内存空间完全隔离?答案不是软件,而是硬件 — 现代CPU的协处理器:MMU
MMU的工作原理,未来我们还会详细阐述,这里只说结论:无论是进程p1,还是进程p2的,它们的变量 a 的地址都是虚拟地址,看上去是同一个地址,但实际上,已经被 MMU 映射到了不同的物理地址上去了。这就是“进程”最显著的特点:空间独立性。
举个例子,进程就像一只井底之蛙,它固执地认为:自己已经拥有整个天空;但它永远不知道:天空到底有多大。更不知道:周围还有很多跟它有一样想法的井底之蛙,而 MMU 就是束缚这些青蛙视野的井,每一口井,就是一个:进程空间。
进程 vs 线程
那看来全是 MMU 惹的祸,不要 MMU 行吗?当然可以,但一旦没有井的束缚,所有的青蛙,都跳到地面上,它们都可以看到一个完整的天空,所以,没有 MMU,进程也就不存在了,进程被降级成了:线程。
这样的例子很多,例如:在没有 MMU 的单片机。你就只会遇到线程或者叫:task,根本没有“进程”的概念。
在 MMU 出现之前,计算机的世界里面,只有“线程”,在 MMU 出现之后,“进程”才真正落地,因为没有 MMU,就没有办法实现:内存空间的隔离,也就根本无法实现“进程”要求的:空间独立性。
至于“进程”中的多“线程”就很容易理解了。就是:一堆青蛙,都放在一个井里。而且,它们都认为自己拥有整个天空。
因为,这些“线程”都处于同一个“进程”空间中,大家可以相互访问,完全没有任何限制。这使得用“线程”实现多任务编程,会非常便利。
但也因为这种对安全的忽视,一旦任何一个“线程”崩溃
所有的“线程”都不能幸免,大家一荣俱荣,一损俱损!
所以,网络服务器一般都会使用“多进程”,而很少使用“多线程”。这样即使某一个用户的服务进程崩溃了,其他“进程”还能继续正常工作。这样,就不会因为某个用户的访问失败,而导致其他用户也无法访问服务器。
好了,这可能就是你永远弄不清楚:“线程”和“进程”的原因,因为,这不仅仅是:一个软件问题,更是一个 MMU 的问题。以后你再跟人讨论“线程”、“进程”的时候,一定要先问一下:有 MMU 吗?
总结
- 进程就像一只井底之蛙,虽然看上去,它可以读/写整个64位(假设CPU是64位的)的虚拟内存空间:void write_memory()
{
char*p = 0;
for(unsigned long offset = 0; offset<= 0xFFFFFFFFFFFFFFFF; offset++)
{
*(p + offset) = 0x55;
}
} 但天到底有多大,真实的物理内存空间到底有多少?除了操作系统和MMU,没有人能知道。 - 进程间的空间隔离,让进程之间的信息共享没有线程那么方便,但也大大提高了整个系统的安全性;再也不会因为某一个应用程序的崩溃,导致计算机重启。还记得红白机上的reset按键吗?
任何一个游戏程序的崩溃,都需要通过reset来重启/恢复系统。
3. 进程间的空间隔离,让恶意程序无法再扫描整其他程序的内存或整个物理内存,任何程序只能在自己的一亩三分地里面干活。通过游戏修改器,玩《仙剑奇侠传》的日子,不会再有了。
这样看来:生活在“井”里,也没有什么不好。
热点问题
Q1:谁在分配:虚拟地址?
A1:程序员在代码中编写的:任何变量、函数、数据结构,在编译过程中,都会被编译器安排了一个内存地址,这个地址就是虚拟地址。
Q2:虚拟内存的好处?
A2:好处是:编译器在生成可执行程序时,可以更加自由的分配:代码中变量的内存地址,不用关心它在实际运行环境中,应该是多少?也不用关心运行环境的内存是否够用。
相同的 exe文件,同时运行2次,也不用担心它们同名的变量或函数,会在内存中重叠在一起。因为它们都用的是虚拟地址,无论外表多么相似,都可能被分配在不同的“物理地址”上。
此外,当程序所需的内存大于计算机的实际内存时,虚拟内存机制可以用硬盘来给内存“扩容”。
Q3:我电脑的内存有8GB,那跑在该电脑上的程序,其虚拟地址空间,也只能有8GB吗?
A3:虚拟地址的空间大小,取决于CPU的位数,32位CPU对应的虚拟地址空间为:0~0xFFFFFFFF(4GB),64位CPU对应的虚拟地址空间为:0~0xFFFFFFFFFFFFFFFF(16384PB),它们跟真实的物理内存大小,没有关系。
Q4:为什么我执行实例代码的时候,输出的 a 的内存地址总是在变化?
A4:新版本的Linux对虚拟内存进行了保护,作了随机化处理,为了达到文章所述的效果,需要取消这种随机化处理。请在运行程序之前,在命令行中输入如下命令:
echo 0 > /proc/sys/kernel/randomize_va_space
参考视频
相关推荐
- linux 查看当前应用内存状况,以及内存参数含义
-
1、查看进程号ps-ef|greptomcat2、查看当前内存分配,200ms打印一次jstat-gc进程号2001jstat-gc344802001S0CS1C...
- 如何显示 Linux 系统上的可用内存?这几个命令很好用!
-
在Linux系统中,了解可用内存是优化系统性能、故障排查以及资源管理的重要一环。本文将详细介绍如何在Linux系统上显示可用内存,包括多种方法和工具的使用。在讨论可用内存之前,我们需要了解一些...
- Linux 下查看内存使用情况方法总结
-
Q:我想监视Linux系统的内存使用情况,在Linux下有哪些视图或者命令行工具可用呢?在做Linux系统优化的时候,物理内存是其中最重要的一方面。自然的,Linux也提供了非常多的方法来监控宝贵的内...
- 2、linux命令-用户管理
-
linux命令-用户管理用户切换[root@eric~]#sueric#切换到用户eric[eric@ericroot]$[eric@ericroot]$su#切换到rootPas...
- Centos 7 进入单用户模式详解
-
1、开机在启动菜单按e进入编辑模式找到linux16行,在最后添加init=/bin/sh编辑完后,按ctrl+x退出2、进单用户模式后,使用passwd修改密码,提示以下错误:passwd:Aut...
- 每日一个Linux命令解析——newusers
-
newusers:在Linux系统中,newusers是一个用于批量创建用户的命令。它从一个文件中读取多行用户信息,每行描述一个用户的详细信息,并根据这些信息创建多个用户或对现有用户进行批量修改。一...
- openEuler操作系统管理员指南:管理用户与用户组
-
在Linux中,每个普通用户都有一个账户,包括用户名、密码和主目录等信息。除此之外,还有一些系统本身创建的特殊用户,它们具有特殊的意义,其中最重要的是管理员账户,默认用户名是root。同时Linux也...
- Linux用户管理
-
1、用户信息文件/etc/passwdroot:x:0:0:root:/root:/bin/bash第一列:用户名第二列:密码位第三列:用户ID0超级用户UID。如果用户UID...
- centos7基础-用户、组、权限管理
-
用户和组(1)用户、组、家目录的概念linux系统支持多用户,除了管理员,其他用户一般不应该使用root,而是应该向管理员申请一个账号。组类似于角色,系统可以通过组对有共性的用户进行统一管理。每个用户...
- LINUX基础 ----------组及用户的概念
-
在Linux中,用户和组都是非常重要的概念,可以控制文件访问权限和资源的管理。用户是标识一个进程、应用程序或系统管理员的账号,Linux中每个用户用一个用户ID(UID)来标识。对于一个...
- 从零入门Linux(四)用户与权限管理
-
在Linux系统中,用户和权限管理是系统安全的重要组成部分。通过合理配置用户和权限,可以确保系统的安全性和资源的合理分配。以下是一些与用户和权限管理相关的常用命令和概念。1.用户管理1.1添加...
- 如何在 Linux 中管理用户?
-
在Linux系统中,用户是系统资源的主要使用者,每个用户都有一个唯一的标识符(用户ID)。为了更好地组织和管理用户,Linux还引入了用户组的概念。用户组是用户的集合,有助于更有效地分配权限和资...
- 在 Linux 中将用户添加到特定组的四种方法
-
在Linux多用户操作系统中,用户组管理是系统安全架构的基石。通过合理的组权限分配,管理员可以实现:精确控制文件访问权限(chmod775project/)简化批量用户权限管理(setfacl-...
- 我不是网管 - 如何在Ubuntu Linux下创建sudo用户
-
Sudo用户是Linux系统的普通用户,具有一定的管理权限,可以对系统执行管理任务。在Linux中,root是超级用户,拥有完全的管理权限,但不建议将root凭证授予其他用户或作为r...
- Linux创建普通用户,为密钥方式登录做准备
-
Hi,我是聪慧苹果8,就是江湖上人见人爱、花见花开,土到掉榨的Linux爱好者,一起学习吧!上一篇关于SSH安全加固的文字,有网友点评通过密钥登录更加安全,先创建一个普通用户,拒绝直接使用密码登录,这...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle忘记用户名密码 (59)
- oracle11gr2安装教程 (55)
- mybatis调用oracle存储过程 (67)
- oracle spool的用法 (57)
- oracle asm 磁盘管理 (67)
- 前端 设计模式 (64)
- 前端面试vue (56)
- linux格式化 (55)
- linux图形界面 (62)
- linux文件压缩 (75)
- Linux设置权限 (53)
- linux服务器配置 (62)
- mysql安装linux (71)
- linux启动命令 (59)
- 查看linux磁盘 (72)
- linux用户组 (74)
- linux多线程 (70)
- linux设备驱动 (53)
- linux自启动 (59)
- linux网络命令 (55)
- linux传文件 (60)
- linux打包文件 (58)
- linux查看数据库 (61)
- linux获取ip (64)
- linux进程通信 (63)