-
进程
一个可执行程序就是一个进程(Process),进程的最显著特点就是
拥有独立的地址空间
。程序:静态概念,存储在磁盘上的一个文件,是指令和数据的集合;
进程:动态概念,程序加载到内存运行后的一系列的活动;
一个进程对应一个地址空间,而一个程序可能会创建多个进程。
-
内核模式与用户模式
用户程序调用系统API函数称为系统调用(System Call);发生系统调用时会暂停用户程序,转而执行内核代码(内核也是程序),访问内核空间,这称为内核模式(Kernel Mode)。
用户空间保存的是应用程序的代码和数据,是程序私有的,其他程序一般无法访问,当执行应用程序自己的代码时,称为用户模式(User Mode)。
用户模式就是执行应用程度代码,访问用户空间;内核模式就是执行内核代码,访问内核空间(当然也有权限访问用户空间)。
-
两种模式的区分源头
内核最主要的任务是管理硬件,包括显示器、键盘、鼠标、内存、硬盘等,并且内核也提供了接口(也就是函数),供上层程序使用。当程序要进行输入输出、分配内存、响应鼠标等与硬件有关的操作时,必须要使用内核提供的接口。但是用户程序是非常不安全的,内核对用户程序也是充分不信任的,当程序调用内核接口时,内核要做各种校验,以防止出错。
从 Intel 80386 开始,出于安全性和稳定性的考虑,CPU 可以运行在 ring0 ~ ring3 四个不同的权限级别,也对数据提供相应的四个保护级别。不过 Linux 和 Windows 只利用了其中的两个运行级别:
- 一个是内核模式,对应 ring0 级,操作系统的核心部分和设备驱动都运行在该模式下。
- 另一个是用户模式,对应 ring3 级,操作系统的用户接口部分(例如 Windows API)以及所有的用户程序都运行在该级别。
-
内核和用户程序共享地址空间
第一节已经说了,一个进程最显著的特点是拥有独立的地址空间,内核和用户共享地址空间,也就是说两者在同一个进程里。
当内核和用户两者切换时,是模式切换,仅仅需要寄存器进栈出栈,不会导致缓存失效。
-
栈
==栈(Stack)==是程序的
虚拟地址空间
中地址较高的一个区域。栈(Stack)可以存放函数参数、局部变量、局部数组等作用范围在函数内部的数据,用途就是完成函数的调用。
栈内存由系统自动分配和释放
:发生函数调用时就为函数运行时用到的数据分配内存,函数调用结束后就将之前分配的内存全部销毁。所以局部变量、参数只在当前函数中有效,不能传递到函数外部。可以把栈理解成一个容器,先进后出(First In Last Out)的存储并利用数据。
入栈(压栈、Push):放入数据;
出栈(弹出、Pop):取出数据;
物理上讲,栈是一段连续的内存,需要同时记录栈底和栈顶,才能定位当前的栈。
ebp 和 esp 都是CPU中的寄存器:ebp 是 Extend Base Pointer 的缩写,通常用来指向栈底;esp 是 Extend Stack Pointer 的缩写,通常用来指向栈顶。
-
栈溢出
栈能用的内存有限,一般是 1M~8M,这在编译时就已经决定了,程序运行期间不能再改变。如果程序使用的栈内存超出最大值,就会发生==栈溢出(Stack Overflow)==错误。
一个程序可以包含多个
线程
,每个线程
都有自己的栈
,严格来说,栈的最大值
是针对线程
来说的,而不是针对程序
。栈内存的大小和编译器有关,编译器会为栈内存指定一个最大值,即可以通过软件设定参数指定。
配置属性–>链接器–>系统–>堆栈保留大小
栈经常被称为堆栈,而堆依然称为堆。
-
C语言变量的存储类别
变量有两个知名属性:
- 数据类型:指明变量占用多大的内存空间,可以进行哪些操作;int、float、double…
- 存储类别:指明变量在内存中的存放区域;auto、static、register、extern
在进程的地址空间中,可以用来存放
变量
的值的区域有:- 常量区:全局变量、静态变量、一般常量、字符串常量
- 全局数据区:全局变量、静态变量、一般常量、字符串常量
- 栈区:局部变量、函数参数
常量区和全局数据区的内存在程序启动时就已经由操作系统分配好,占用的空间固定,程序运行期间不再改变,程序运行结束后才由操作系统释放;
栈区的内存在程序运行期间由系统根据需要来分配(使用到变量才分配内存;如果定义了变量但没有执行到该代码,也不会分配内存),占用的空间实时改变,使用完毕后立即释放,不必等到程序运行结束;
生存期指的是在程序运行过程中,变量从创建到销毁的一段时间,生存期的长短取决于变量的
存储类别
,也就是它所在的内存区域
。知道了变量的存储类别,就可以知道变量的生存期。
-
auto
自动或默认,定义变量时加不加auto都一样,一般可省略;
int n = 10; # 等同于 auto int n = 10;
-
static
静态变量,不管是全局还是局部的,都存储在
静态数据区
(全局变量本来就存储在静态数据区,可以不加static)静态数据区的数据在程序启动时就会初始化,直到程序运行结束;对于代码块中的静态局部变量,即使代码块执行结束,也不会销毁。
-
register
寄存器变量。
变量的值是存储在内存中的,CPU 每次使用数据都要从内存中读取。如果有一些变量使用非常频繁,从内存中读取就会消耗很多时间,可以将使用频繁的变量放在CPU的
通用寄存器
中,这样使用该变量时就不必访问内存,直接从寄存器中读取,大大提高程序的运行效率。 -
References
C语言与内存需要知道的事情:进程、地址空间、用户模式、内核模式、栈、数据类型、存储类型、静态变量、寄存器变量
最新推荐文章于 2024-01-24 11:42:10 发布