Linux——虚拟内存

来源:互联网 发布:美姿堂专业彩妆护淘宝 编辑:程序博客网 时间:2024/06/05 23:56

问题的提出

pro1.c

#include <stdio.h>#include <stdlib.h>main(){int *a=malloc(4);*a=9999;//*(a+1)=1000;//*(a+1000)=10000;printf("%p\n",a);while(1);}

gcc pro1.c -omain1    运行 main1   结果:0x8a01008


pro2.c

#include <stdio.h>#include <stdlib.h>main(){int *a=(int*)0x8a01008;//逻辑地址 没有与之相对应的物理地址 要建立关联才有意义 这个过程就是内存映射printf("%d\n",*a);while(1);}

猜会不会打印9999

gcc pro2.c -omain2    运行 main2   结果:段错误

    原因:
        一个程序不能访问另外一个程序的地址指向的空间.
    理解:
        1.每个程序的开始地址0x80084000
        2.程序中使用的地址不是物理地址,而是逻辑地址(虚拟内存).
          逻辑地址仅仅是编号.编号使用int 4字节整数表示.
          4294967296=4G
          每个程序提供了4G的访问能力
    问题:
        逻辑地址与物理地址关联才有意义:过程称为内存映射.

    结论:
        虚拟地址与物理地址映射的时候有一个基本单位:至少会映射4K
                4k  1000 内存页.
        段错误:无效访问. 那段内存没有映射
        非合法访问:比如malloc分配的空间之外的空间可以访问(没有段错误),但访问非法.因是越界访问

        内存访问分两种:一个是可以访问,但不一定是合法的,比如malloc几个字节,
        内存会给你映射4K空间,int* p=malloc(0); *(p+1000)=9999;理论说这是可以访问

四。虚拟内存的分配
        栈:编译器自动生成代码维护,我们不用关心
        堆:我们关心地址是否映射,映射的空间是否被管理。
        1.brk/sbrk 内存映射函数
            
            
        补充:帮助手册
            man 节  关键字  
            1-8  1:Linux系统(shell)指令  man 1 ls;
                            
                 2:系统函数 man 2 brk;
                 3:标准C函数 man fopen 一般在2和3节找
                            
                 7:系统编程帮助    man 7 tcp(icmp;udp;socket)
            
            分配释放内存:        
            int brk(void *end);//分配空间,释放空间

            void *sbrk(int size);//返回空间分配前的地址 然后内存内部当前指针移动size

            应用:
                1.使用sbrk分配空间 sbrk(非零整数)
                2.使用sbrk得到没有映射的虚拟地址.第一次调用sbrk,sbrk(0)得到的是没有映射的虚拟首地址。
                3.使用brk分配空间
                4.使用brk释放空间

brk.c

#include <stdio.h>#include <unistd.h>main(){/*int *p=sbrk(0);没有映射空间的虚拟地址*p=8888;*/ //会出现段错误int *p1=sbrk(4);//分配4个字节 映射了一个页 内部当前指针移动4字节*p1=8888;//*(p+1024)=7777;//段错误*(p1+1023)=7777;//没有段错误printf("%d\n",*p1);}

          
            应用案例:
                写一个程序查找1-10000之间所有的素数.见demo1.c
                并且存放到缓冲,然后打印.
                    
                缓冲的实现使用sbrk/brk
                流程:
                    循环
                        判定是否素数(isPrimer)
                        是,分配空间存放
                        不是,继续下步.

demo.c

#include <stdio.h>#include <unistd.h>int isPrimer(int a){int i;for(i=2;i<a;i++){if(a%i==0){return 1;}}return 0;}main(){int i=2;int b;int *r;int *p;p=sbrk(0);r=p;for(;i<100;i++){b=isPrimer(i);if(b==0){brk(r+1);*r=i;r=sbrk(0);}}i=0;r=p;while(r!=sbrk(0)){printf("%d\n",*r);r++;}brk(p);//free}


            总结:
                智能指针
                stl
                new
                malloc
                brk/sbrk比较适合大空间
            异常处理
                int brk(void*)
                void *sbrk(int);
                如果成功.brk返回0   sbrk返回指针
                失败 brk返回-1  sbrk返回(void*)-1

memerr.c

#include <string.h>#include <errno.h>#include <stdlib.h>#include <unistd.h>#include <stdio.h>extern int errno;int main(){void *p=sbrk(1000000000*3);if(p==(void*)-1){//perror("Hello:");//printf("Memory:%m\n");printf("::%s\n",strerror(errno));}}

                   
                Unix函数错误,修改内部变量:errno
            
            字符串函数string.h  cstring
            内存管理函数malloc memset mamcmp memcpy ...
                    bzero
            错误处理函数
            标准IO函数
            时间函数
            类型转换函数

1 0
原创粉丝点击