xiwenAndlejian / my-blog

Java基础学习练习题
1 stars 0 forks source link

操作系统 - 内存段 #11

Open xiwenAndlejian opened 5 years ago

xiwenAndlejian commented 5 years ago

操作系统 - 内存段

《操作系统思考》读书笔记

《操作系统思考》

内存段

运行中的进程数据组织为4个段:

以上段的组织方式部分取决于编译器,部分取决于操作系统。不同的操作系统中细节可能不同,但是下面这些是共同的:

操作系统内存段

代码示例

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

可以看出:

静态局部变量

栈上的局部变量有时被称为:自动变量,因为它们当函数创建时自动被分配,并且当函数返回时自动被释放

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