1-Linux 系统总内存

1.内存使用情况

我们一般会使用free命令来查看系统的内存使用情况,如下

root@zihome:# free
             total         used         free       shared      buffers
Mem:        125848        57332        68516            0         3160
-/+ buffers:              54172        71676
Swap:        62460            0        62460

我们再使用/proc/meminfo来看下,应该会更加直观

root@zihome:/# cat /proc/meminfo
MemTotal:         125848 kB
MemFree:           68436 kB
Buffers:            3160 kB
Cached:            15100 kB
SwapCached:            0 kB
Active:            14932 kB
Inactive:          11948 kB
Active(anon):       8724 kB
Inactive(anon):       76 kB
Active(file):       6208 kB
Inactive(file):    11872 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:         62460 kB
SwapFree:          62460 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:          8656 kB
Mapped:             9908 kB
Shmem:               180 kB
Slab:              12484 kB
SReclaimable:       1804 kB
SUnreclaim:        10680 kB
KernelStack:        1008 kB
PageTables:          536 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:      125384 kB
Committed_AS:      96256 kB
VmallocTotal:    1048372 kB
VmallocUsed:       12076 kB
VmallocChunk:    1025184 kB

Linux在内存的使用上的宗旨是:如果内存充足,不用白不用,尽量用内存来缓存一些文件,从而加快进程的运行速度,而当内存不足时,这些内存又会被回收,供程序使用。

所以真正可用的内存是:MemFree + Buffers + Cached = 68436 + 3160 +15100 = 86696

2.虚拟内存和物理内存

我们在上面用命令查到的是物理内存的使用情况,实际在写代码的时候我们面对的是虚拟内存,在32为操作系统上,每个进程有4GB的内存空间,不过真正使用的是3G用户空间,有1G是内核空间,是和所有程序共享。

image.png

一张典型的C语言在linux系统下的占区图:
在这里插入图片描述

可以看出,对于Linux系统下的,存储空间的分配有着较为层次清晰的分层。单片机大概也遵循这个分区架构。

  • 二进制代码以及常量(CONST修饰)以及全局变量在最底层,存储空间最靠前的部分
  • 然后是堆区,堆区向上增长,我们常用到的molloc()、free()等函数操作的就是这个区,这也是芯片系统中唯一可以让程序员通过代码操作的一片存储空间
  • 再然后是动态链接库
  • 在往上(高地址)便是栈区,由编译器自动分配和释放,存放函数的参数值、局部变量的值等。
  • 最高地址一般为操作系统内核,用户无法访问

一个正常的程序在内存中通常分为程序段、数据端、堆栈三部分

  • 程序代码区,存放函数体的二进制代码。
  • 文字常量区,常量字符串就是放在这里的,程序结束后由系统释放
  • 全局区(静态区)(static),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量、未初始化的静态变量在相邻的另一块区域,程序结束后有系统释放
  • 堆区(heap)一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
  • 栈区(stack),由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

如下例子:

int a=0;   //全局初始化区
char *p1;   //全局未初始化区

main()
{
    int b;   //栈
    char s[]="abc";   //栈
    char *p3= "1234567";     //在文字常量区Flash
    static int c =0 ;        //静态初始化区
    p1= (char *)malloc(10);  //堆区
    strcpy(p1,"123456");    //"123456"放在常量区
}
  • 在调用malloc的时候其实实在堆区(虚拟内存)申请了空间
  • 知道使用strcpy的时候才真正使用内存,所以这时候才分配了物理内存使用。

在每个进程的maps里面可以看到每个区多处于的地址范围。

root@zihome:/proc/1821# cat maps
00400000-0042a000 r-xp 00000000 1f:05 660        /usr/sbin/dropbear
0043a000-0043b000 rw-p 0002a000 1f:05 660        /usr/sbin/dropbear
00581000-00584000 rw-p 00000000 00:00 0          [heap]
00584000-0059b000 rw-p 00000000 00:00 0          [heap]
77ed8000-77f2f000 r-xp 00000000 1f:05 786        /lib/libuClibc-0.9.33.2.so
77f2f000-77f3e000 ---p 00000000 00:00 0
77f3e000-77f3f000 r--p 00056000 1f:05 786        /lib/libuClibc-0.9.33.2.so
77f3f000-77f40000 rw-p 00057000 1f:05 786        /lib/libuClibc-0.9.33.2.so
77f40000-77f45000 rw-p 00000000 00:00 0
77f45000-77f5b000 r-xp 00000000 1f:05 766        /lib/libgcc_s.so.1
77f5b000-77f6a000 ---p 00000000 00:00 0
77f6a000-77f6b000 rw-p 00015000 1f:05 766        /lib/libgcc_s.so.1
77f6b000-77f6e000 r-xp 00000000 1f:05 775        /lib/libcrypt-0.9.33.2.so
77f6e000-77f7d000 ---p 00000000 00:00 0
77f7d000-77f7e000 rw-p 00002000 1f:05 775        /lib/libcrypt-0.9.33.2.so
77f7e000-77f8f000 rw-p 00000000 00:00 0
77f8f000-77f90000 r-xp 00000000 1f:05 765        /lib/libutil-0.9.33.2.so
77f90000-77f9f000 ---p 00000000 00:00 0
77f9f000-77fa0000 rw-p 00000000 1f:05 765        /lib/libutil-0.9.33.2.so
77fa0000-77fa7000 r-xp 00000000 1f:05 798        /lib/ld-uClibc-0.9.33.2.so
77fb4000-77fb6000 rw-p 00000000 00:00 0
77fb6000-77fb7000 r--p 00006000 1f:05 798        /lib/ld-uClibc-0.9.33.2.so
77fb7000-77fb8000 rw-p 00007000 1f:05 798        /lib/ld-uClibc-0.9.33.2.so
7ff69000-7ff8a000 rwxp 00000000 00:00 0          [stack]
7fff7000-7fff8000 r-xp 00000000 00:00 0          [vdso]

内存的分配最小单位是4KB,反正内存的申请和释放都是根据代码申请多少就是多少,这样频繁的申请释放肯定消耗性能,所以只malloc一点点,也会申请4+128KB

在申请小内存的时候使用malloc,系统调用brk来调整堆顶的地址(超过原本的限制,就会往上一直调整),当申请大内存的时候,会使用mmap申请,这时候就会直接开辟一个新的堆地址空间。

而栈的扩展就是通过压栈的方式,因为栈是在最上面的地方,所以就往下一直调整

优化数据段的方法

1.尽可能减少全局变量和静态变量

2.对于非内置类型的全局变量(类,结构体),尽可能使用全局对象指针来代替

3.将只读的全局变量,加上const,从而使其转移到代码段,利用代码段是系统共享的特性达到节省内存是哟个的目的

4.不要在头文件中定义变量

动态库

动态库在程序编译的时候不会被链接到目标代码中,而是在程序运行时才被载入,因此在程序运行时还需要动态库的存在(除了拷贝可执行文件,还要拷贝到/usr/lib/里面去)。

动态库有数据段和代码段组成(堆\栈属于调用这个动态库的进程所有)

代码段的共享性,所以一个动态库被多个进程调用,就会有多个数据段,但是只有一个代码段。

1.去掉无用的动态库readelf查看依赖的动态库

2.动态库的合并

3.仅被依赖一次的动态库

静态库

静态库在程序编译时会被链接到目标代码中,程序运行时将不再需要加载静态库。

linux C语言 内存申请 堆 栈 大小限制:https://blog.csdn.net/xxxxxx91116/article/details/10068555

Linux内存分配机制:https://www.cnblogs.com/wangliangblog/p/9109384.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值