操作系统 - 内存段
Opened this issue · 0 comments
操作系统 - 内存段
《操作系统思考》读书笔记
内存段
运行中的进程数据组织为4
个段:
text段
:包含程序文本,即程序锁组成的机器语言指令。static段
:包含编译器所分配的变量,包括全局变量,和使用static
声明的局部变量。stack段
:包含运行时栈,它由栈帧组成。每个栈帧包含函数参数、本地变量以及其他。heap
段:包含运行时分配的内存块,通常通过调用C标准库函数malloc
来分配。
以上段的组织方式部分取决于编译器,部分取决于操作系统。不同的操作系统中细节可能不同,但是下面这些是共同的:
text段
:靠近内存==底部==,即接近0
的地址。static段
:通常刚好在text
段上面。stack段
:靠近内存顶部,即接近虚拟地址空间的最大地址。在扩张过程中,它向低地址的方向增长。heap段
:通常在static
段的上面。在扩张过程中,它向高地址的方向增长。
代码示例
aspace.c
:
#include <stdio.h>
#include <stdlib.h>
int global;
int main()
{
int local = 5;
void *p = malloc(128);
printf ("Address of main is %p\n", main);
printf ("Address of golbal is %p\n", &global);
printf ("Address of local is %p\n", &local);
printf ("Address of p is %p\n", p);
}
代码解释
main
:是函数的名称,当它用作变量时,它指向main
中第一条机器语言指令的地址,我们认为它在text
段内。
global
:是一个全局变量,所以我们认为它在static
段内。
local
:是一个局部变量,所以我们认为它在stack
上。
p
:持有malloc
所返回的地址,它指向堆区所分配的空间。malloc
代表内存分配(memory allocate)
格式化占位符%p
告诉printf
把每个地址格式化为指针,它是地址的另一个名字。
执行结果
Address of main is 0x10f79cea0
Address of golbal is 0x10f79d020
Address of local is 0x7ffee046323c
Address of p is 0x7fd51de00000
可以看出:
地址:main < golbal < p < local
即如上文所说:text < static < heap < stack
练习
添加对
malloc
的第二个调用来检查系统上的堆是否向上增长(地址变大)。添加一个函数来打印出局部变量的地址,来检查栈是否向下增长
aspace2.c
:
#include <stdio.h>
#include <stdlib.h>
int global;
void hello()
{
int local = 5;
int local2 = 1;
printf ("Address of local is %p\n", &local);
printf ("Address of local2 is %p\n", &local2);
}
int main()
{
void *p = malloc(128);
void *q = malloc(128);
printf ("Address of main is %p\n", main);
printf ("Address of golbal is %p\n", &global);
printf ("Address of p is %p\n", p);
printf ("Address of p is %p\n", q);
hello();
}
执行结果
Address of main is 0x1085dfe70
Address of golbal is 0x1085e0020
Address of p is 0x7fa164402b50
Address of q is 0x7fa164402bd0
Address of local is 0x7ffee762042c
Address of local2 is 0x7ffee7620428
地址从低到高:main < golbal < p < q < local2 < local
可以看出:
- 通过
malloc
函数,在heap
上分配空间,所得地址向上增长 - 声明
局部变量
,在stack
上分配空间,所得地址向下增长
静态局部变量
栈上的局部变量有时被称为:自动变量,因为它们当函数创建时自动被分配,并且当函数返回时自动被释放。
C语言中有另一种局部变量,叫做静态变量,它被分配在static
段上。在程序启动时初始化,并且在函数调用之间保存它的值。
例子
int times_called()
{
static int counter = 0;
counter++;
return counter;
}
static
关键字表示counter
是静态局部变量。它的初始化只在程序启动时发生。
实际执行
Address of main is 0x108746e80
Address of golbal is 0x108747024
Address of local is 0x7ffee74b945c
Address of p is 0x7f9d5ac02b50
Address of counter is 0x108747020
可以看出counter
是和golbal
一起被分配在static
上了
counter
的地址小于golbal
是否意味着static
也是向下增长的?
在golbal
下面增加一个全局静态变量golbal2
,打印他们的地址:
Address of main is 0x10e08de50
Address of golbal is 0x10e08e024
Address of golbal2 is 0x10e08e028
Address of local is 0x7ffee1b7245c
Address of p is 0x7fc957c02b50
Address of counter is 0x10e08e020
可以看出:counter < golbal < golbal2
,新增的静态变量地址变大了
置于为什么counter
地址会比golbal
更小,猜测是因为加载顺序中,函数在变量前,因此优先初始化了counter
。