Linux——内存管理

一 .学习体系

   语言: C C++

   算法:  算法 数据结构

   基础(系统核心Kernek编程):
     Linux/Unix  Window  MacOSX  
     pc  服务器 ARM
   
   操作系统五大能力:设备驱动/进程管理/内存管理/文件目录管理/IO
   
    内存管理
    文件目录
    IO
    进程管理:进程创建  进程控制 进程通信  进程同步
    线程管理:线程创建,同步(控制,控制),通信


   应用:网络  数据库(pro*c/c++) UI(QT)  shell编程

定位:提高编程的能力,为设备驱动与window应用奠定基础


二 内存管理

     硬件层次:内存结构管理
    内核层次:内存映射  堆扩展
    语言层次:c:malloc  c++:new

    数据结构层次:STL(厂商:sgi 惠普 IBM )  智能指针

实例代码

malloc.c

#include <stdio.h>
#include <stdlib.h>
int main()
{
	int *p1 = new int;
	int *p2 = new int;
	int *p3 = new int;
	int *p4 = new int;
	int *p5 = new int;
	//int *p1 = malloc(4);
	//int *p2 = malloc(4);
	//int *p3 = malloc(4);
	//int *p4 = malloc(4);
	//int *p5 = malloc(4);
	
	printf("%p\n",p1);
	printf("%p\n",p2);
	printf("%p\n",p3);
	printf("%p\n",p4);
	printf("%p\n",p5);
	
	return 0;
	
}

1.问题:malloc怎么分配空间? malloc与new的关系?

2.Linux对内存的描述

示例代码

test.c

#include <unistd.h>
#include <stdio.h>
main()

{
               printf("%d\n",getpid());
               while(1);

}

gcc test.c -omain      main  

输入命令行 ps aue 查看进程号

    /proc/$(pid)/  存放进程运行时候所有的信息(包括内存结构)

然后在另起一个终端 cd /proc/进程号   ls即可看到该进程有关的文件

cat maps(查看程序运行时所有的内存结构)

 结论:任何程序的内存空间分成4个基本部分    (工具 ldd 可执行程序 查看可执行程序依赖哪些动态库)

          1)代码区(有个动态库把程序加载到代码空间 代码区首地址是固定的 主函数全局常量 调用函数放代码区) 可以这样执行main函数 /lib/ld-linux.so.2 main 该动态库是个可执行文件 将程序加载到代码空间并将首地址定位到main 并且分配全局栈
          
          2)全局栈区
          3)堆  
          4)局部栈

 2.理解程序的变量与内存空间的关系 见varmem.c 再见statckleap.c


varmem.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int add(int a,int b)
{
	return a+b;
}
int a1=1;
static int a2=2;
const int a3=3;

main()
{
	int b1=4;
	static b2=5;
	const b3=6;
	
	int *p1=malloc(4);
	
	printf("a1:%p\n",&a1);//全局区
	printf("a2:%p\n",&a2);//全局区
	printf("a3:%p\n",&a3);//代码区
	printf("b1:%p\n",&b1);//栈
	printf("b2:%p\n",&b2);//全局区
	printf("b3:%p\n",&b3);//栈
	printf("p1:%p\n",p1);//堆
	printf("main:%p\n",main);//代码区
	printf("add:%p\n",add);//代码区
	
	printf("%d\n",getpid());
	while(1);
}

statckleap.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

main()
{
	int a1=10;
	int a2=20;
	int a3=30;
	
	int *p1=malloc(4);
	int *p2=malloc(4);
	int *p3=malloc(4);
	
	printf("%p\n",&a1);<span style="font-family: Arial, Helvetica, sans-serif;">//0xbff82048</span>
	printf("%p\n",&a2);<span style="font-family: Arial, Helvetica, sans-serif;">//0xbff8204c</span>
	printf("%p\n",&a3);<span style="font-family: Arial, Helvetica, sans-serif;">//0xbff82048</span>
	printf("%p\n",p1);<span style="font-family: Arial, Helvetica, sans-serif;">//0x9dee008</span>
	printf("%p\n",p2);<span style="font-family: Arial, Helvetica, sans-serif;">//</span><span style="font-family: Arial, Helvetica, sans-serif;">0x9dee018</span>
	printf("%p\n",p3);//<span style="font-family: Arial, Helvetica, sans-serif;">0x9dee028</span>

	
	printf("%d\n",getpid());
	while(1);
}

 3.理解malloc的工作原理
    malloc使用一个数据结构(链表)来维护分配空间
    链表的构成:分配的空间/上一个空间的数据/下一个空间/空间大小等信息
    对malloc分配的空间不要越界访问,因为容易破坏后台的维护结构,导致malloc/free
    /calloc/realloc不能正常工作

示例代码

mallocstruct.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

main()
{
	
	int *p1=malloc(4);
	int *p2=malloc(4);
	int *p3=malloc(4);
	
	*p1=1;
	*(p1+1)=2;
	*(p1+2)=3;
	*(p1+3)=4;
	*(p1+4)=5;
	*(p1+5)=6;
	*(p1+6)=7;
	*(p1+7)=8;
        
        //free(p1);会出错链表结构被破坏		
	printf("%d\n",*p2);
	

}


  4.C++的new与malloc的关系
    malloc   new      new[]
    realloc  new()定位分配
    calloc   new[]
    free     delete   delete[]


newmalloc.cpp

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
	int *p1=(int*)malloc(4);
	int *p2=new int;
	int *p3=(int*)malloc(4);
	int *p4=new int;
	int *p5=new int;
	int *p6=new int;
	//Stu *p=new Stu[30];
	
	//delete p;
	//delete[] p;
	
				
	printf("%p\n",p1);
	printf("%p\n",p2);
	printf("%p\n",p3);
	printf("%p\n",p4);
	printf("%p\n",p5);
	printf("%p\n",p6);
	return 0;
}
    结论:new的实现使用的是malloc来实现的
     区别:new使用malloc后,还要初始化空间
             基本类型,直接初始化成默认值(int成0 bool类型是false)
                UDT(用户自定义的)类型,直接调用指定的构造器
         delete调用free实现
        delete负责调用析构器,然后再调用free
     new与new[]区别:
    new只调用一个构造器初始化
     new[]循环对每个区域调用构造器
     delete与delete[]区别: Stu *p =  new Stu[30]  delete p(释放一个);delete[]p(释放一组);
       

 5.函数调用栈空间的分配与释放
      函数执行时使用栈空间作为自己的临时栈,3种方式决定编译器清空栈的方式
       5.1.总结:
      1.函数执行的时候有自己的临时栈(在局部栈里).
        C++成员函数拥有两个栈空间,一个是函数本身的栈空间,另一个是对象的栈空间
        因为函数本身是在对象的栈空间里运行
        C里函数只有一个栈空间

       2.函数的参数就在临时栈中.如果函数传递实参.则用来初始化临时参数变量.
        不管哪种传递,实质传递的都是值,一般变量传的是数据,而指针传的是地址值        
       3.通过寄存器返回值.(使用返回值返回数据)
       4.通过参数返回值.(参数必须是指针)
        指针指向的区域必须事先分配.
       5.如果参数返回指针.参数就是双指针.
                    
    5.2.__stdcall __cdecl __fastcall
      1.决定函数栈压栈的参数顺序.    
      2.决定函数栈的清空方式:不管是哪种方式,都是在编译时编译器负责产生清空栈的函数            代码
        _stdcall表示每个调用者负责清空自己调用的函数的临时栈
        _fastcall函数自己在返回前自己清空临时栈,然后返回值退出
        _cdecl表示所有调用者只有一个清空函数来负责清空所有被调用函数的临时栈
      3.决定了函数的名字转换方式.在底层其实并不支持重载,会转换成不同的函数名。
        在window下,函数名前加_stdcall


 6.far near huge指针
    near 16位
    far 32位
    huge综合
    Win32统一采用far指针,这三个指针在window下会碰到


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值