分享

linux查看系统空闲内存的方法

 cupid 2016-01-15

本博文为原创,遵循CC3.0协议,转载请注明出处:http://blog.csdn.net/lux_veritas/article/details/19231993

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


1. free -m

2. 用户态程序中,利用sysinfo系统调用

3. 内核态程序中,我没有找到很好的方法,通过追踪sysinfo系统调用的流程,定位实现函数。最终利用do_sysinfo中的si_meminfo实现


linux系统中,查看当前内存的使用情况,简便的方法是free命令,命令行中free -m,列出系统当前的可用内存、cache/buffer、swap相关信息。

free工具是procps项目提供的标准proc文件系统分析工具,通过读取分析/proc/meminfo,实时的反应当前系统的内存使用情况。项目主页:procps.


如果想在程序中实时查看系统当前可用内存情况,可以利用的方法也是多样的。

1. 如果是在用户态程序中查看,可以通过“system”系统调用,执行free命令,或是读取/proc/meminfo文件,再做文本处理。

2. 当然1的方法不够直观,/proc/meminfo中的信息是系统利用proc文件系统的处理函数获得的,内核代码fs/proc/meminfo.c中实现的。

粗读代码可以发现struct sysinfo这个结构(include/linux/kernel.h中定义)

  1. struct sysinfo {  
  2.          long uptime;                    /* Seconds since boot */  
  3.          unsigned long loads[3];         /* 1, 5, and 15 minute load averages */  
  4.          unsigned long totalram;         /* Total usable main memory size */  
  5.          unsigned long freeram;          /* Available memory size */  
  6.          unsigned long sharedram;        /* Amount of shared memory */  
  7.          unsigned long bufferram;        /* Memory used by buffers */  
  8.          unsigned long totalswap;        /* Total swap space size */  
  9.          unsigned long freeswap;         /* swap space still available */  
  10.          unsigned short procs;           /* Number of current processes */  
  11.          unsigned short pad;             /* explicit padding for m68k */  
  12.          unsigned long totalhigh;        /* Total high memory size */  
  13.          unsigned long freehigh;         /* Available high memory size */  
  14.          unsigned int mem_unit;          /* Memory unit size in bytes */  
  15.          char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */  
  16.  };  

可以看到该结构中定义了系统的内存使用情况。源码中查询sysinfo,发现有sysinfo这个系统调用,用于查询和获得系统信息。

于是在用户态程序中可以采用如下方法:

  1. #include <stdio.h>  
  2. #include <unistd.h>  
  3. #include <linux/kernel.h>  
  4.   
  5. int main()  
  6. {  
  7.     struct sysinfo sys;  
  8.     int err = sysinfo(&sys);  
  9.     printf("\n\nerror code is: %d\n", err);  
  10.   
  11.     printf( "free mem:\t%ld\n"                                                                                 
  12.             "total mem:\t%ld\n"  
  13.             "buffer mem:\t%ld\n",   
  14.             sys.freeram, sys.totalram, sys.bufferram   
  15.           );    
  16.   
  17.     return 0;  
  18. }  

在内核态中实现,我没有找到很好的方法。通过读代码,找到执行sysinfo系统调用的回调函数sys_sysinfo,查找源码没有发现sys_sysinfo函数的实现,必定又是挨千刀的内核的某些宏来定义的...尝试多种syscall相关的宏定义,结合sysinfo出现的位置,定位到

SYSCALL_DEFINE1(sysinfo, struct sysinfo __user *, info)
宏展开SYSCALL_DEFINE1得到验证。

  1. SYSCALL_DEFINE1(sysinfo, struct sysinfo __user *, info)  
  2. {  
  3.         struct sysinfo val;  
  4.   
  5.         do_sysinfo(&val);  
  6.   
  7.         if (copy_to_user(info, &val, sizeof(struct sysinfo)))  
  8.                 return -EFAULT;  
  9.   
  10.         return 0;  
  11. }  

核心实现函数为do_sysinfo函数,该函数执行内容过多,为免除不必要操作,只利用与freeram相关的函数操作,即:si_meminfo函数。

  1. void si_meminfo(struct sysinfo *val)  
  2. {  
  3.         val->totalram = totalram_pages;  
  4.         val->sharedram = 0;  
  5.         val->freeram = global_page_state(NR_FREE_PAGES);  
  6.         val->bufferram = nr_blockdev_pages();  
  7.         val->totalhigh = totalhigh_pages;  
  8.         val->freehigh = nr_free_highpages();  
  9.         val->mem_unit = PAGE_SIZE;  
  10. }  

可以看到,sysinfo中的ram相关内容被赋值。写一个内核模块做测试:

  1. #include <linux/init.h>  
  2. #include <linux/module.h>  
  3. #include <linux/kernel.h>  
  4. #include <linux/mm.h>  
  5. #include <asm/page.h>  
  6.   
  7. MODULE_LICENSE("GPL");  
  8. MODULE_AUTHOR("GuoHongwei");  
  9.   
  10. static int sysinfo_init()  
  11. {  
  12.     struct sysinfo sys;  
  13.     // int err = do_sysinfo(&sys);  
  14.   
  15.     si_meminfo(&sys);  
  16.   
  17.     // printk("\n\nerror code is: %ld", err);  
  18.     printk("free mem is: %ld\n", (sys.freeram << (PAGE_SHIFT - 10)));  
  19.   
  20.     return 0;  
  21. }  
  22.   
  23. static void sysinfo_exit()  
  24. {  
  25.     printk("exit module sysinfo_test\n");  
  26. }  
  27.   
  28. module_init(sysinfo_init);  
  29. module_exit(sysinfo_exit);  

Makefile:
  1. obj-m := sysinfo_test.o  
  2. KERNELDIR = /lib/modules/$(shell uname -r)/build                                                               
  3. PWD := $(shell pwd)  
  4.   
  5. default:  
  6.         make -C $(KERNELDIR) M=$(PWD) modules  
  7.   
  8. clean:  
  9.         make -C $(KERNELDIR) M=$(PWD) clean  

执行结果如下:




    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多