现在的位置: 首页 > 综合 > 正文

Linux虚拟内存-brk/sbrk

2018年03月21日 ⁄ 综合 ⁄ 共 3777字 ⁄ 字号 评论关闭

虚拟内存

              问题:

                            一个程序不能访问另外一个程序的地址指向的空间.

              理解:

                            1.每个程序的开始地址0x80084000

                            2.程序中使用的地址不是物理,而是逻辑地址(虚拟内存).

                                          逻辑地址仅仅是编号.编号使用int 4字节整数表示.

                                          4294967296

                                          每个程序提供了4G的访问能力

              问题:

                                   逻辑地址与物理地址关联才有意义:过程称为内存映射.

              背景:

                                   虚拟内存的提出:禁止用户直接访问物理存储设备.

                                   有助于系统的稳定.

                                  

              结论:

                                   虚拟地址与物理地址映射的时候有一个基本单位:

                                                        4k  1000 内存页.

                                   段错误:无效访问.

                                   合法访问:比如malloc分配的空间之外的空间可以访问,但访问非法.

                                  

虚拟内存的分配.

                     栈:编译器自动生成代码维护

                     堆:地址是否映射,映射的空间是否被管理.

                     1.brk/sbrk内存映射函数

                    

                     分配释放内存:            

                     intbrk(void *end);//分配空间,释放空间

                     void*sbrk(int size);//返回空间地址

                     应用:

                                   1.使用sbrk分配空间/size为正 分配空间 size为负 可释放空间

                                   2.使用sbrk得到没有映射的虚拟地址.

                                   3.使用brk分配空间

                                   4.使用brk释放空间

                     理解:

                                   sbrk(int  size)

                                   sbrk与brk后台系统维护一个指针.

                                   指针默认是null.

                                   调用sbrk,判定指针是否是0,是:得到大块空闲空间的首地址初始化指针.同时把指针+size

                               否:返回指针,并且把指针位置+size

例子:Linux下

代码1:

#include<stdio.h>

#include<unistd.h>

 

void main()

{

     int * p1=sbrk(0);     //得到大块空闲空间的首地址初始化指针

     int * p2=sbrk(4);     //分配4个字节的空间先返回空闲空间的首地址,在将指针加4

     int * p3=sbrk(4);     //同理,返回的指针地址为上一次sbrk返回的地址+size

     printf(“%p\n”,p1);

     printf(“%p\n”,p2);

     printf(“%p\n”,p3);

}

 

运行结果:

0x9d9d000           sbrk(0)返回的空闲空间首地址

0x9d9d000        sbrk(0)返回的空间地址,并把地址+size(0x9d9d004)0x9d9d000-0x9d9d004为sbrk(4)分配的4个字节的空间

0x9d9d004            再次调用sbrk(4),返回的指针为地址0x9d9d004,指针再次+size

                     0x9d9d004-0x9d9d008为这次调用sbrk分配的4个字节的空间

 

代码2:

#include<stdio.h>

#include<unistd.h>

 

void main()

{

   int* p=sbrk(0);     //返回空闲空间的首地址,但系统并没有给虚拟内存映射物理内存

  *p=800;           //会出现段错误,无法访问p指向的地址的空间

  brk(p+1);          //brk(p+1) 是把p指针向后移了4个字节,系统把虚拟内存映射到了//物理内存(映射了一个页的物理内存4k),brk分配了4个字节的//动态内存空间

  *p=800;           //不会出现段错误

  brk(p);            //brk(p)又把指针向回移了4个字节,释放了4个字节的空间

  *p=800;           //则不能再访问p的空间

  

}

 

应用案例:

                                   写一个程序查找1-10000之间所有的素数.

                                   并且存放到缓冲,然后打印.

                                  

                                   缓冲的实现使用sbrk/brk

                                   流程:

                                                 循环

                                                               判定是否素数(isPrimer)

                                                               是,分配空间存放

                                                               不是,继续下步.

 

代码:

#include<stdio.h>

#include<unistd.h>

 

int isprimer(int a)

{

     intI;

    for(i=2;i<a;i++)

    {

          if(a%i==0)

                return 1;

          else

                 return 0;

    }

}

 

void main()

{

    int i=2;

    int *p=sbrk(0);

    int *r;

    r=p;

    for(;i<1000;i++)

    {

          if(isprimer(i)==0)

          {

                brk(r+1);

                *r=i;

                r=sbrk(0);

          }

    }

 

r=p;

while(r!=sbrk(0))

{

      printf(“%d\n”,*r);

      r++

}

}

brk(p); //free

 

              brk/sbrk

                     异常处理

                                   intbrk(void*)

                                   void*sbrk(int);

                                   如果成功.brk返回0  sbrk返回指针

                                                 失败 brk返回-1  sbrk返回(void*)-1

 

抱歉!评论已关闭.