2018-11-12 11:12:35 dataiyangu 阅读数 2173

原文地址:http://www.voidcn.com/article/p-yehrvmep-uo.html

思路如下:Linux系统中可以用top命令查看进程使用CPU和内存情况,通过Runtime类的exec()方法执行命令"top”,获取"top"的输出,从而得到CPU和内存的使用情况。

使用top命令获取系统信息: 

top -b -n -1 | sed -n '3p'(使用sed命令将top输出内容中的第三行打印出来)

%Cpu(s):  6.5 us,  2.2 sy,  0.7 ni, 87.0 id,  3.5 wa,  0.0 hi,  0.1 si,  0.0 st

top -b -n 1 | sed -n '3p' | awk '{print $8}'(将第三行第八列打印出来)

87.0

获取单个进程CPU,内存的占用率 

cmd脚本命令:top -b -n 1 -p $pid |  sed -n '$p' 
上面的$pid,就是进程的PID 

Java Runtime类

每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。 

应用程序不能创建自己的 Runtime 类实例。

 

示例程序(针对suse平台,如果是其他Linux,可能需要稍微修改程序)

 

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class MySystem {

	public static float getCpuUsage() {
		float cpuUsage = 0;
		float idleUsage = 0;
		Runtime rt = Runtime.getRuntime();
		String[] cmd = { "/bin/sh", "-c",
				"top -b -n 1 | sed -n '3p' | awk '{print $5}'" };<span style="color:#ff0000;"><strong>//如果使用的命令带有空格、重定向等,必须使用命令串(字符串数组)</strong></span>
		BufferedReader in = null;
		String str = "";
		try{
		Process p = rt.exec(cmd);
		in = new BufferedReader(new InputStreamReader(p.getInputStream()));
		str = in.readLine();
		}catch(Exception e){
			
		}
		str = str.substring(0,3);
		idleUsage = Float.parseFloat(str);
		cpuUsage = 100 - idleUsage;
		cpuUsage = FormatFloat.formatFloat(cpuUsage);
		System.out.println("CpuUsage:");
		System.out.println("	"+cpuUsage);
		return cpuUsage;
	}
	
	public static void getCPUMEMByPID(){
		Runtime rt = Runtime.getRuntime();
		String[] cmd = { "/bin/sh", "-c",
				"top -b -n 1 | sed -n '3p' | awk '{print $5}'" };
		BufferedReader in = null;
		String str = "";
		try{
		Process p = rt.exec(cmd);
		in = new BufferedReader(new InputStreamReader(p.getInputStream()));
		str = in.readLine();
		}catch(Exception e){
			
		}
	}
	
	public static float getMemUsage() {
		long memUsed = 0;
		long memTotal = 0;
		float memUsage = 0;
		Runtime rt = Runtime.getRuntime();
		String[] cmd = { "/bin/sh", "-c",
				"top -b -n 1 | sed -n '4p' | awk '{print $2 \"\t\" $4}'" };
		BufferedReader in = null;
		String str = "";
		try{
			Process p = rt.exec(cmd);
			in = new BufferedReader(new InputStreamReader(p.getInputStream()));
			str = in.readLine();
		}catch(Exception e){
			
		}
		
		String[] mems = str.split("\t");
		mems[0] = mems[0].substring(0,mems[0].length()-2);
		memTotal = Long.parseLong(mems[0]);
		mems[1] = mems[1].substring(0,mems[1].length()-2);
		memUsed = Long.parseLong(mems[1]);
		memUsage = (float) memUsed / memTotal * 100;
		memUsage = FormatFloat.formatFloat(memUsage);
		System.out.println("MemUsage:");
		System.out.println("	"+memUsage);
		return memUsage;
	}

}


获取cpu、内存的使用率还有其他方法

 

proc文件系统(http://www.cnblogs.com/yoleung/articles/1638922.html,http://blog.csdn.net/blue_jjw/article/details/8741000)

参考文章:http://zengjz88.iteye.com/blog/1595535 http://cumtyjp.blog.163.com/blog/static/7611480820093157512732/ http://blog.csdn.net/hemingwang0902/article/details/4054709

相关文章

相关标签/搜索

2018-01-23 16:31:45 ZC20141220 阅读数 1221

共享内存区是最快的IPC(进程间通信)形式。

用共享内存从服务器拷贝文件数据到客户端:


共享内存基本API:

#include<sys/ipc.h>

#include<sys/shm.h>

1.     int shmget(key_t key,size_t size,int shmflg);

功能:用来创建共享内存

key:是这个共享内存段的名字
size:共享内存的大小
shmflg:相当于权限位(如0666)
返回值是共享内存段的标识码shmid,
例如:shmid = shmget(0x1111, 128, 0666);
    //创建共享内存 , 相当于打开打开文件 
 //若共享内存存在 则使用   fopen()
 //若共享内存 不存在 则报错 -1

shmid = shmget(0x1111, 128, 0666 | IPC_CREAT);
     //创建共享内存 , 相当于打开打开文件 
   //若共享内存存在 则使用   fopen()
  //若共享内存 不存在 则创建 


shmid = shmget(0x1111, 128, 0666 | IPC_CREAT | IPC_EXCL);
 //创建共享内存 , 相当于打开文件 
//若共享内存存在 则报错
//若共享内存 不存在 则创建 
//作用 IPC_EXCL判断存在不存在的标志  避免已经存在的文件 被覆盖

2.  void *shmat(int shmid, const void *shmaddr, int shmflg);0xaa11

功能:将共享内存段连接到进程地址空间

shmaddr:指定连接的地址,因为内存地址是段页式管理,所以有可能传入的地址并不就是那一页的开头位置,所以传入一个地址,传出的仍然是一个地址,传出的是具体开始存储的地址。所以我们通常传入NULL,让编译器直接分配个合适的位置给我们。

shmflg:它的两个取值可能是SHM_RND和SHM_RDONLY.

例: void *p = shmat(shmid, NULL, 0);

返回值:成功返回一个指针,指向共享内存第一个节,失败返回-1;


3, int shmdt(const void *shmaddr);

功能:将共享内存段与当前进程脱离,但并不等于删除共享内存段


4,  int shmctl(int shmid,int cmd,struct shmid_ds *buf);

功能:用于控制共享内存

cmd:将要采取的动作

1,IPC_STAT  把shmid_ds结构中的数据设置为共享内存的当前关联值

2,IPC_SET    在进程有足够权限的前提下,把共享内存的当前关联值设置为shmid_ds数据结构中给出的值

3,IPC_RMID  删除共享内存段

buf: 指向一个保存着共享内存的模式状态和访问权限的数据结构

   例: shmctl(shmid, IPC_RMID, NULL);

   //删除共享内存

若想要把旧的共享内存里面的内容保存下来,则传入一个地址,用来完成保存的功能


为什么链接共享内存时要设计shmid,创建时要传入key:

共享内存私有:





Linux内核通过引用计数技术来管理共享内存生命周期







2018-01-23 12:47:05 linuxweiyh 阅读数 1942

在用户空间动态申请内存

在用户空间中动态申请内存的函数为 malloc(),这个函数在各种操作上的使用都是一致的。与之对应的释放函数为 free()。

对于 Linux 而言,C 库的 malloc() 函数一般通过 brk() 和 mmap() 两个系统调用从内核申请内存。


在内核空间动态申请内存

在 Linux 内核空间中申请内存涉及的函数主要包括 kmalloc()、__get_free_pages() 和 vmalloc() 等。这里只介绍这3种。

1. kmalloc()

函数原型为:

void * kmalloc(size_t size, int flags);

size:要分配的块的大小

flags:分配标志,用于控制 kmalloc() 的行为,最常用是 GFP_KERNEL 和 GFP_ATOMIC

分配标志为 GFP_KERNEL 时,表示在内核空间的进程中申请内存。

使用 GFP_KERNEL 标志申请内存时,若暂时不能满足,则进程会睡眠等待也,即会引起阻塞,因此不能中断上下文或持有自旋锁的时候使用 GFP_KERNEL 申请内存。

由于在中断处理函数、tasklet 和内核定时器等非进程上下文中不能阻塞,所以此时驱动应当使用 GFP_ATOMIC 标志来申请内存。当使用 GFP_ATOMIC 标志申请内存时,若不存在空页,则不等待,直接返回。

2. __get_free_pages()

__get_free_pages() 系列函数/宏本质上是 Linux 内核最底层用于获取空闲内存的方法,因为底层的 buddy 算法以 2N 页为单位管理空闲内存,所以最底层的内存申请总是以 2N 页为单位的。

__get_free_pages() 系列函数/宏包括 get_zeroed_page()、__get_free_page() 和 __get_free_pages()。

kmalloc() 的底层依赖于 __get_free_pages() 来实现的。

3. vmalloc()

vmalloc() 一般只为存在于软件中(没有对应的硬件意义)的较大的顺序缓冲区分配内存,vmalloc() 远大于 __get_free_pages() 的开销,为了完成 vmalloc(),新的页表项需要被建立,因此,只是调用 vmalloc() 来分配少量的内存时不妥的。

vmalloc() 申请的内存使用 vfree() 释放。

vmalloc() 不能用在原子上下文中,因为它的内部实现了标志位 GFP_KERNEL 的 kmalloc()。

vmalloc() 在申请内存时,会进行内存的映射,改变页表项,不像 kmalloc() 实际用的是开机过程中就映射好的 DMA 和常规区域的页表项。因此 vmalloc() 的虚拟地址和物理地址不是一个简单的线性映射。

4. 总结

kmalloc() 和 __get_free_pages() 申请的内存在物理上连续,而 vmalloc() 申请的内存在物理上不连续。

2014-08-24 00:32:09 zhaoyw2008 阅读数 10227

转自:http://blog.csdn.net/pcliuguangtao/article/details/6526119/

共享内存是LUNIX 系统中最底层的通信机制,也是最快速的通信机制。共享内存通过两个或多个进程共享同一块内存区域来实现进程间的通信。通常是由一个进程创建一块共享内存区域,然后多个进程可以对其进行访问,一个进程将要传出的数据存放到共享内存中,另一个或多个进程则直接从共享内存中读取数据。因此这种通信方式是最高效的进程间通信方式。但实际的问题在于,当两个或多个进程使用共享内存进行通信时,同步问题的解决显得尤为重要,否则就会造成因不同进程同时读写一块共享内存中的数据而发生混乱。在通常的情况下,通过使用信号量来实现进程的同步。

  1. /*共享内存允许两个或多个进程进程共享同一块内存(这块内存会映射到各个进程自己独立的地址空间) 
  2.   从而使得这些进程可以相互通信。 
  3.   在GNU/Linux中所有的进程都有唯一的虚拟地址空间,而共享内存应用编程接口API允许一个进程使 
  4.   用公共内存区段。但是对内存的共享访问其复杂度也相应增加。共享内存的优点是简易性。 
  5.   使用消息队列时,一个进程要向队列中写入消息,这要引起从用户地址空间向内核地址空间的一次复制, 
  6.   同样一个进程进行消息读取时也要进行一次复制。共享内存的优点是完全省去了这些操作。 
  7.   共享内存会映射到进程的虚拟地址空间,进程对其可以直接访问,避免了数据的复制过程。 
  8.   因此,共享内存是GNU/Linux现在可用的最快速的IPC机制。 
  9.   进程退出时会自动和已经挂接的共享内存区段分离,但是仍建议当进程不再使用共享区段时 
  10.   调用shmdt来卸载区段。 
  11.   注意,当一个进程分支出父进程和子进程时,父进程先前创建的所有共享内存区段都会被子进程继承。 
  12.   如果区段已经做了删除标记(在前面以IPC——RMID指令调用shmctl),而当前挂接数已经变为0, 
  13.   这个区段就会被移除。 
  14.  */  
  15. /* 
  16.   shmget(  )  创建一个新的共享内存区段 
  17.               取得一个共享内存区段的描述符 
  18.   shmctl(  )  取得一个共享内存区段的信息 
  19.               为一个共享内存区段设置特定的信息 
  20.               移除一个共享内存区段 
  21.   shmat(  )   挂接一个共享内存区段 
  22.   shmdt(  )   于一个共享内存区段的分离 
  23.  */  
  24. //创建一个共享内存区段,并显示其相关信息,然后删除该内存共享区  
  25. #include <stdio.h>  
  26. #include <unistd.h>  //getpagesize(  )  
  27. #include <sys/ipc.h>  
  28. #include <sys/shm.h>  
  29. #define MY_SHM_ID 67483  
  30. int main(  )  
  31.     {  
  32.         //获得系统中页面的大小  
  33.         printf( "page size=%d/n",getpagesize(  ) );  
  34.         //创建一个共享内存区段  
  35.         int shmid,ret;  
  36.         shmid=shmget( MY_SHM_ID,4096,0666|IPC_CREAT );  
  37.         //创建了一个4KB大小共享内存区段。指定的大小必须是当前系统架构  
  38.         //中页面大小的整数倍  
  39.         if( shmid>0 )  
  40.             printf( "Create a shared memory segment %d/n",shmid );  
  41.         //获得一个内存区段的信息  
  42.         struct shmid_ds shmds;  
  43.         //shmid=shmget( MY_SHM_ID,0,0 );//示例怎样获得一个共享内存的标识符  
  44.         ret=shmctl( shmid,IPC_STAT,&shmds );  
  45.         if( ret==0 )  
  46.             {  
  47.                 printf( "Size of memory segment is %d/n",shmds.shm_segsz );  
  48.                 printf( "Numbre of attaches %d/n",( int )shmds.shm_nattch );  
  49.             }  
  50.         else  
  51.             {  
  52.                 printf( "shmctl(  ) call failed/n" );  
  53.             }  
  54.         //删除该共享内存区  
  55.         ret=shmctl( shmid,IPC_RMID,0 );  
  56.         if( ret==0 )  
  57.             printf( "Shared memory removed /n" );  
  58.         else  
  59.             printf( "Shared memory remove failed /n" );  
  60.         return 0;  
  61.     }  
  62.   
  63. //共享内存区段的挂载,脱离和使用  
  64. //理解共享内存区段就是一块大内存  
  65. #include <stdio.h>  
  66. #include <sys/shm.h>  
  67. #include <sys/ipc.h>  
  68. #include <errno.h>  
  69. #define MY_SHM_ID 67483  
  70. int main(  )  
  71.     {  
  72.         //共享内存区段的挂载和脱离  
  73.         int shmid,ret;  
  74.         void* mem;  
  75.         shmid=shmget( MY_SHM_ID,0,0 );  
  76.         if( shmid>=0 )  
  77.             {  
  78.                 mem=shmat( shmid,( const void* )0,0 );  
  79.                 //shmat()返回进程地址空间中指向区段的指针  
  80.                 if( ( int )mem!=-1 )  
  81.                     {  
  82.                         printf( "Shared memory was attached in our address space at %p/n",mem );  
  83.                         //向共享区段内存写入数据  
  84.                         strcpy( ( char* )mem,"This is a test string./n" );  
  85.                         printf( "%s/n",(char*)mem );  
  86.                         //脱离共享内存区段  
  87.                         ret=shmdt( mem );  
  88.                         if( ret==0 )  
  89.                             printf( "Successfully detached memory /n" );  
  90.                         else  
  91.                             printf( "Memory detached failed %d/n",errno );  
  92.                     }  
  93.                 else  
  94.                     printf( "shmat(  ) failed/n" );  
  95.                   
  96.             }  
  97.         else  
  98.             printf( "shared memory segment not found/n" );  
  99.         return 0;  
  100.     }  
  101. /*内存共享区段与旗语和消息队列不同,一个区段可以被锁定。 
  102.   被锁定的区段不允许被交换出内存。这样做的优势在于,与其 
  103.   把内存区段交换到文件系统,在某个应用程序调用时再交换回内存, 
  104.   不如让它一直处于内存中,且对多个应用程序可见。从提升性能的角度 
  105.   来看,很重要的。 
  106.  */  
  107. int shmid;  
  108. //...  
  109. shmid=shmget( MY_SHM_ID,0,0 );  
  110. ret=shmctl( shmid,SHM_LOCK,0 );  
  111. if( ret==0 )  
  112.     printf( "Locked!/n" );  
  113. ////////////////////////////////////////////////////////////////////////  
  114. /*使用旗语协调共享内存的例子 
  115.   使用和编译命令 
  116.   gcc -Wall test.c -o test 
  117.   ./test create 
  118.   ./test use a & 
  119.   ./test use b & 
  120.   ./test read & 
  121.   ./test remove  
  122.  */  
  123. #include <stdio.h>  
  124. #include <sys/shm.h>  
  125. #include <sys/ipc.h>  
  126. #include <sys/sem.h>  
  127. #include <string.h>  
  128. #include <stdlib.h>  
  129. #include <unistd.h>  
  130. #define MY_SHM_ID 34325  
  131. #define MY_SEM_ID 23234  
  132. #define MAX_STRING 200  
  133. typedef struct  
  134. {  
  135.     int semID;  
  136.     int counter;  
  137.     char string[ MAX_STRING+1 ];  
  138. }MY_BLOCK_T;  
  139. int main(int argc,char** argv)  
  140.     {  
  141.         int shmid,ret,i;  
  142.         MY_BLOCK_T* block;  
  143.         struct sembuf sb;  
  144.         char user;  
  145.         //make sure there is a command  
  146.         if( argc>=2 )  
  147.             {  
  148.                 //create the shared memory segment and init it  
  149.                 //with the semaphore  
  150.               if( !strncmp(argv[ 1 ],"create",6) )  
  151.                     {  
  152.                         //create the shared memory segment and semaphore  
  153.                         printf( "Creating the shared memory/n" );  
  154.                         shmid=shmget( MY_SHM_ID,sizeof( MY_BLOCK_T ),( IPC_CREAT|0666 ) );  
  155.                         block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 );  
  156.                         block->counter=0;  
  157.                         //create the semaphore and init  
  158.                         block->semID=semget(MY_SEM_ID,1,( IPC_CREAT|0666 ));  
  159.                         sb.sem_num=0;  
  160.                         sb.sem_op=1;  
  161.                         sb.sem_flg=0;  
  162.                         semop( block->semID,&sb,1 );  
  163.                         //now detach the segment  
  164.                         shmdt( ( void* )block );  
  165.                         printf( "Create the shared memory and semaphore successuflly/n" );  
  166.                           
  167.                     }  
  168.                 else if( !strncmp(argv[ 1 ],"use",3) )  
  169.                     {  
  170.                         /*use the segment*/  
  171.                         //must specify  also a letter to write to the buffer  
  172.                         if( argc<3 ) exit( -1 );  
  173.                         user=( char )argv[ 2 ][ 0 ];  
  174.                         //grab the segment  
  175.                         shmid=shmget( MY_SHM_ID,0,0 );  
  176.                         block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 );  
  177.                           
  178.                         /*##########重点就是使用旗语对共享区的访问###########*/  
  179.                         for( i=0;i<100;++i )  
  180.                         {  
  181.                             sleep( 1 ); //设置成1s就会看到 a/b交替出现,为0则a和b连续出现  
  182.                         //grab the semaphore  
  183.                         sb.sem_num=0;  
  184.                         sb.sem_op=-1;  
  185.                         sb.sem_flg=0;  
  186.                         if( semop( block->semID,&sb,1 )!=-1 )  
  187.                             {  
  188.                                 //write the letter to the segment buffer  
  189.                                 //this is our CRITICAL SECTION  
  190.                                 block->string[ block->counter++ ]=user;  
  191.                                   
  192.                                 sb.sem_num=0;  
  193.                                 sb.sem_op=1;  
  194.                                 sb.sem_flg=0;  
  195.                                 if( semop( block->semID,&sb,1 )==-1 )  
  196.                                     printf( "Failed to release the semaphore/n" );  
  197.                                   
  198.                             }  
  199.                         else  
  200.                             printf( "Failed to acquire the semaphore/n" );  
  201.                         }  
  202.                           
  203.                        //do some clear work  
  204.                         ret=shmdt(( void*)block);  
  205.                           
  206.                     }  
  207.                 else if( !strncmp(argv[ 1 ],"read",4) )  
  208.                     {  
  209.                         //here we will read the buffer in the shared segment  
  210.                         shmid=shmget( MY_SHM_ID,0,0 );  
  211.                         if( shmid!=-1 )  
  212.                             {  
  213.                                 block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 );  
  214.                                 block->string[ block->counter+1 ]=0;  
  215.                                 printf( "%s/n",block->string );  
  216.                                 printf( "Length=%d/n",block->counter );  
  217.                                 ret=shmdt( ( void*)block );  
  218.                              }  
  219.                         else  
  220.                             printf( "Unable to read segment/n" );  
  221.                   
  222.                     }  
  223.                 else if( !strncmp(argv[ 1 ],"remove",6) )  
  224.                     {  
  225.                         shmid=shmget( MY_SHM_ID,0,0 );  
  226.                         if( shmid>=0 )  
  227.                             {  
  228.                                 block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 );  
  229.                                 //remove the semaphore  
  230.                                 ret=semctl( block->semID,0,IPC_RMID );  
  231.                                 if( ret==0 )  
  232.                                     printf( "Successfully remove the semaphore /n" );  
  233.                                 //remove the shared segment  
  234.                                 ret=shmctl( shmid,IPC_RMID,0 );  
  235.                                 if( ret==0 )  
  236.                                     printf( "Successfully remove the segment /n" );  
  237.                             }  
  238.                     }  
  239.                 else  
  240.                     printf( "Unkonw command/n" );  
  241.             }  
  242.         return 0;  
  243.           
  244.     }  


++++++++++++++++++++++++++++++++++++++++++

以下两个程序是一个进程间通信的例子。这两个程序分别在不同的进程中运行,使用了共享内存进行通信。b从键盘读入数据,存放在共享内存中。a则从共享内存中读取数据,显示到屏幕上。由于没有使两个进程同步,显示的内容将是杂乱无章的.实例b程序负责向共享内存中写入数据,a程序负责从内存中读出共享的数据,它们之间并没有添加同步操作。

b.c

#include <sys/types.h>   
#include <sys/ipc.h>   
#include <sys/shm.h>   
#include <stdio.h>   
  
#define BUF_SIZE 1024   
#define MYKEY 25   
int main()  
{  
    int shmid;  
    char *shmptr;  
  
    if((shmid = shmget(MYKEY,BUF_SIZE,IPC_CREAT)) ==-1)  
    {  
    printf("shmget error \n");  
    exit(1);  
    }  
  
    if((shmptr =shmat(shmid,0,0))==(void *)-1)  
    {  
    printf("shmat error!\n");  
    exit(1);  
    }  
  
    while(1)  
    {  
    printf("input:");  
    scanf("%s",shmptr);  
    }  
  
    exit(0);  
} 

=======================================

a.c
#include <stdio.h>   
#include <sys/types.h>   
#include <sys/ipc.h>   
#include <sys/shm.h>   
  
#define BUF_SIZE 1024   
#define MYKEY 25   
int  main()  
{  
    int shmid;  
    char * shmptr;  
  
    if((shmid = shmget(MYKEY,BUF_SIZE,IPC_CREAT)) ==-1)  
    {  
    printf("shmget error!\n");  
    exit(1);  
    }  
  
    if((shmptr = shmat(shmid,0,0)) == (void *)-1)  
    {  
    printf("shmat error!\n");  
    exit(1);  
    }  
  
    while(1)  
    {  
    printf("string :%s\n",shmptr);  
    sleep(3);  
    }  
  
    exit(0);  
}  



2016-10-08 16:50:26 kelsel 阅读数 1856

http://www.sealinger.com/archives/406/
linux系统内存实际使用率

图中的例子很典型,就是:多数的linux系统在free命令后会发现free(剩余)的内存很少,而自己又没有开过多的程序或服务。

对于上述的情况,正确的解释是:

linux的内存管理机制与windows的有所不同。具体的机制我们无需知道,我们需要知道的是,linux的内存管理机制的思想包括(不敢说就是)内存利用率最大化。内核会把剩余的内存申请为cached,而cached不属于free范畴。当系统运行时间较久,会发现cached很大,对于有频繁文件读写操作的系统,这种现象会更加明显。

直观的看,此时free的内存会非常小,但并不代表可用的内存小,当一个程序需要申请较大的内存时,如果free的内存不够,内核会把部分cached的内存回收,回收的内存再分配给应用程序。所以对于linux系统,可用于分配的内存不只是free的内存,还包括cached的内存(其实还包括buffers)

1、通过定期采集/proc文件系统内的meminfo文件来获取当前内存使用情况:


proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为访问系统内核数据的操作提供接口。用户和应用程序可以通过proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取proc文件时,proc文件系统是动态从系统内核读出所需信息并提交的采集流程图。

/proc/meminfo 信息如下:

需要使用的指标有:MemTotal ,MemFree,Buffers,Cached

MemTotal:总内存大小
MemFree: 空闲内存大小
Buffers和Cached:磁盘缓存的大小

Buffers和Cached的区别:

buffers 是指用来给块设备做的缓冲大小,他只记录文件系统的metadata以及 tracking in-flight pages.
cached 是用来给文件做缓冲。
buffers 是用来存储目录里面有什么内容,权限等等。
而cached直接用来记忆我们打开的文件,比如先后执行两次命令#man X ,你就可以明显的感觉到第二次的开打的速度快很多。
而buffers随时都在增加,比如先后两次使用ls /dev后,就会发现第二次执行的速度会较第一次快。
这就是buffers/chached的区别。

2、下面分别从操作系统角度和应用程序角度来区别Buffers和Cached


使用free命令可以看到

对操作系统来说,Buffers和Cached是已经被使用的(上图Mem:这一行)

MemFree=total-used
314952=24946552-24631600

对应用程序来说(上图对应-/+ buffers/cache那一行)

MemFree=buffers+cached+free
19536392=152116+19069324+314952

所以本着监控应用对物理内存使用情况的目的采取如下计算方法:

内存使用率(MEMUsedPerc)=100*(MemTotal-MemFree-Buffers-Cached)/MemTotal

在这里为了PatrolAgent的监控性能,采用定期读取/proc/meminfo文件来获取MemTotal ,MemFree,Buffers,Cached这些参数的值
该算法在MEMORY.km中实现。

===============================================================

通过看free命令的说明可以发现,free命令的数值是从/proc/meminfo文件重读取的。查看free的源码包查看其源码,明确知道了其中的每个数值的来源(具体内容可查看linux命令free源码解读:Procps free.c)。
有时我们计算内存使用率的时候会读取free命令的回显,但有时也会直接读取文件/proc/meminfo的内容,毕竟free命令的回显数据就是从meminfo文件中获得的。

然而,由于不同的linux发行版,在系统制作过程中会修改部分源码。一般的系统(如Debian)使用free命令和读取meminfo文件两种方式计算的内存使用率是相同的。但是对于部分系统,如SUSE(并不确定是每个版本的都是,这里指SUSE Enterprise Server 11),其在free命令回显的结果中,cached部分的值并不等于meminfo文件中的cached所显示的值,而是等于meminfo文件中cached部分和SReclaimable部分之和。

也就是说,debian之类的系统认为:

可用内存=free的内存+cached的内存+buffers的内存

而SUSE之类的系统则认为:

可用内存=free的内存+cached的内存+buffers的内存+SReclaimable的内存

PS:什么是SReclaimable?在linux内核中会有许多小对象,这些对象构造销毁十分频繁,比如i-node,dentry。这么这些对象如果每次构建的时候就向内存要一个页,而其实际大小可能只有几个字节,这样就非常浪费,为了解决这个问题就引入了一种新的机制来处理在同一页框中如何分配小存储器区,这个机制可以减少申请和释放内存带来的消耗,这些小存储器区的内存称为Slab。meminfo文件中标识了Slab的大小,而SReclaimable是指可收回Slab的大小。

<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(10632) | 评论(0) | 转发(1) |
0

上一篇:CAN'T OPEN DISPLAY

下一篇:博客搬家

给主人留下些什么吧!~~
评论热议

linux内核内存分配

阅读数 5681