Linux——虚拟内存

问题的提出

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函数
            时间函数
            类型转换函数

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值