1. 程式人生 > >[c++,kernel] 獲取當前程序記憶體佔用量

[c++,kernel] 獲取當前程序記憶體佔用量

實驗目的:

通過系統呼叫實現獲取當前正在執行的程序佔用系統中的記憶體資源的最大值,

由於涉及到系統庫中的API 所以將其歸類為kernel方向。

實驗思路:

希望本程式可以被 windows 和 linux/unix  所相容,所以程式設計實現時過程中通過巨集定義

方法來判斷當前平臺型別,然後根據不同的平臺型別呼叫不同的系統  API 來得到系統的引數。

但是在程式碼中僅給出 window 下面的程式碼及說明(使用 #ifdef 來分辨平臺在 vs2012 中沒有除錯成功)

實驗環境:

vs2012 , c++

實驗程式碼:

//memChecker.h

#ifndef   MEMCHECKER_H
#define  MEMCHECKER_H

namespace memChecker
{
	long get_maxMem_kb () ;
}
#endif //MEMCHECKER_H

//memChecker.cpp

#include "memChecker.h"

#include <Windows.h>
#include <Psapi.h>

using namespace memChecker;

long memChecker::get_maxMem_kb()
{
	PROCESS_MEMORY_COUNTERS pmc ;
	GetProcessMemoryInfo(GetCurrentProcess() , &pmc, sizeof(pmc));
	return pmc.PeakWorkingSetSize / 1024 ;
}

 

//Main.cpp

#include <cstdio>
#include <cstdlib>
#include <iostream>

#include "memChecker.h"

using namespace std ;

int main ( int argc , char * argv [] )
{
	cout<<"here is the current maxmum memory "<<endl;  
	long usage = memChecker::get_maxMem_kb() ;

	cout<<usage<<endl ;

	system("pause") ;
	return 0 ;
}
其中,對於 memChecker.cpp 中所涉及到的 windows 核心程式碼註釋如下:

1. 變數 PROCESS_MEMORY_COUNTERS 

1.
PROCESS_MEMROY_COUNTERS

typedef struct _PROCESS_MEMORY_COUNTERS
{
DWORD cb ;
DWORD PageFaultCount ;
SIZE_T    PeakWorkingSetSize ;
SIZE_T    WorkingSetSize ;
SIZE_T    QuotaPeakPagePoolUsage ;
SIZE_T    QuotaPagedPoolUsage ;
SIZE_T     QuotaPeakNonPagedPoolUsage ;
SIZE_T    QuotaNonPagedPoolUsage ;
SIZE_T     PagefileUsage ;
SIZE_T    PeakPagefileUsage ;
} PROCESS_MEMORY_COUNTERS , *PROCESS_MEMORY_COUNTERS ;

PROCESS_MEMORY_COUNTERS 
這個變數是用來記錄系統中當前程序,也就是 PROCESS_MOMORY_COUNTERS
變數所在的這個程式執行起來之後對應的這個程序對系統記憶體資源的使用量的一系列統計資料。


其中 DWORD 是一個 Microsoft  中定義的一個變數型別,
可以將它看作是一個類似於char 型別,不過 char 對應的是一個字元號,
而DWORD 是 double word ,每個 word 是 2個位元組的大小, 那麼DWORD 就是長度為 4 個位元組大小的一個變數型別。

而SIZE_T 是屬於c++標準庫中的一個型別, 他是一個與機器相關的無符號的型別(unsigned)。 

1. cb:
以位元組為單位用來記錄 當前這個 PROCESS_MEMORY_COUNTERS 型別對應的變數
所佔的大小,即 
PROCESS_MEMORY_COUNTERS pmd ;
pmd.cb = sizeof(pmd) ;

2. PageFaultCount:
用來記錄發生頁錯誤的次數

3. PeakWorkingSetSize
以位元組為單位,用來記錄當前工作集的大小

4. QuotaPeakPagedPoolUsage
以位元組為單位,記錄分頁池中最大的使用量

5. QuotaPagedPoolUsage
以位元組為單位,記錄當前分頁池中的使用量(即分頁池中被程序申請的全部頁面的大小(kb))

6. QuotaPeakNonPagedPoolUsage
以位元組為單位記錄非分頁池中最大的空間申請量

7. QuotaNonPagedPoolUsage
以位元組為單位,記錄非分頁池中當前空間的申請使用量
(注: 這裡的空間均是指系統中的記憶體空間 ;我想:在分頁池中空間的分配是以 頁面為單位的, 
而在非分頁池中記憶體空間的分配大小是由申請空間大小來分配的)

8.PagefileUsage
commit charge is a term used in Microsoft Windows operating systems to describe
 the total amount of pageable virtual address space for
 which no backing store is assigned other than the pagefile.
<這裡的 commit charge 是記憶體的一種: 在微軟的作業系統中時用來描述所有可分頁虛擬地址空間的總數目,
其中這些虛擬地址空間中全部是是頁面檔案存放空間,而不包含快取空間(backing store)>

而這個PagefileUsage 是以位元組為單位來記錄當前程序所佔用的 Commit Charge 型別記憶體的大小數值的。
Commit Charge 在官網中也給出解釋,說它是有記憶體管理者為當前正在執行的繼承所分配的全部記憶體的一個總數。

9. PeakPagefileUsage
這個變數是用來以位元組為單位記錄,系統為當前程序在該程序的生命週期內所分配的
最大Commit Charge型別記憶體的最大值。


2. method: GetProcessMemoryInfo 
2), Mehtod : GetProcessMemoryInfo
從它的名字即可推知它的功能,用來獲取明確指定程序
的記憶體使用情況資訊。

這個系統API的設計方式與 unix/linux 常用的系統API 設計方式很相似:
都是通過返回值來返回該方法執行的是否正確的情況,
並且通過 "值-地址" 的傳參方式來得到該函式真正的返回數值。
這一點"值-地址" 的傳參方式可以從如下的API描述中看出來:
即, _In_ 表示的是,該引數是傳入到方法中的數值,
_Out_ 所表示的是,該引數傳入的是一個指向空間的地址變數,(指標),
在該函式中得到執行結果之後,通過傳入的指標將結果寫入到指標所指向的空間中即可。
這樣在方法結束返回到主調方法中之後,存放結果的空間並不會隨著子方法的執行結束
而被釋放掉,主調方法仍舊可以通過剛剛傳入到子方法中的指標來對該指標指向空間進行訪問。

其中,BOOL 後面的 WINAPI 以意思是表明該函式是 windows中的系統API,
系統 API 並不是系統呼叫,而是系統為程式設計師使用系統呼叫提供的一個介面函式。
在該API中(系統API)呼叫的是真正的核心中的系統方法,也就是系統呼叫。

知道這一點十分重要,因為這會直接影響你編寫程式所站的角度:

是以一名使用者的身份,還是以計算機的身份。
如果你想修改系統核心程式碼的話,是必須要站在計算機的身份來思考整個程式的走向的。

反之,如果你只想訪問,讀取系統當前的某些狀態,
那麼你必須以使用者的身份來思考問題。
 
BOOL WINAPI GetProcessMemoryInfo
(
_In_    HANDLE Process ,
_Out_ PROCESS_MEMORY_COUNTERS ppmc,
_IN_  DWORD cb 
) ;


其中第一個引數是用來傳入想要獲取資訊的程序物件的控制代碼,
因為本方法只是想獲取當前的程序使用記憶體的情況,
所以在本方法中呼叫一個
GetCurrentProcess() 即可得到當前程序的控制代碼。
這裡所說的控制代碼,類似於物件的一種引用(reference),通過引用可以
確定該物件(該程序)在系統中存放的位置、大小等相關資訊。

<在這裡我是這麼想的(僅僅是推理,沒有實際求證):
 雖然普通類的引用(reference )於Process 的控制代碼(handler )亦或是一個物件實體的指標(pointer ),
所起到的作用都是相類似的,在這裡撇開指標不說,只談引用和控制代碼。

二者之所以區分對待,是因為Process 這個資料結構物件是系統內部的資料結構物件,
而引用所指代的應該是使用者自定義的類物件,二者佔用的記憶體空間應該是有所區別的。
系統對引用和控制代碼的維護方式,即其相應的空間回收、訪問和管理方式有所不同的原因>

1.Process : [傳入引數] 接收要分析佔用記憶體空間資訊的程序物件的控制代碼
2.ppmc:[傳入、傳出引數] 接收指向 PROCESS_MEMORY_COUNTERS 結構體物件的指標
                    通過傳入的指標將分析結果記錄到該指標指向的空間中,方法結束空間不會被回收
                    (空間是由系統為主調方法分配的,而並非是 GetProcessMemoryInfo 方法中的區域性變數佔用的空間)
3. cb       :[傳入引數] 該數值用來描述 PROCESS_MEMORY_COUNTERS 實體指標所指向的實體佔用空間的大小。
即 cb = sizeof (*pmd ) ; 或是 cb = (*ppmc)->cb ;


3. Method :GetCurrentProcess 
3).Method:  GetCurrentProcess() 

HANDLE WINAPI GetCurrentProcess (void ) ;

該方法是 windows 中的系統API , 返回值是當前正在執行的程序的控制代碼物件。
那什麼叫做當前執行的程序呢? 就是你呼叫該 GetCurrentProcess() 語句所在的程式,
在該程式被執行起來之後,對於 GetCurrentProcess () 而言就是它的當前正在執行的程序。

實驗不足與改進:

這個程式碼中不能加入自動識別執行平臺的巨集定義,很是遺憾沒能夠寫上 linux 訪問記憶體使用資訊的系統函式。

巨集定義還需要在仔細學習一下。

相關推薦

[c++,kernel] 獲取當前程序記憶體用量

實驗目的: 通過系統呼叫實現獲取當前正在執行的程序佔用系統中的記憶體資源的最大值, 由於涉及到系統庫中的API 所以將其歸類為kernel方向。 實驗思路: 希望本程式可以被 windows 和 linux/unix  所相容,所以程式設計實現時過程中通過巨集定義 方法來

C++ 獲取當前程序載入模組的完整路徑讀取配置檔案

C++ 獲取當前程序已載入模組的檔案的完整路徑操作配置檔案: char buf[MAX_PATH]; ZeroMemory(buf, MAX_PATH);

獲取當前程序的CPU使用率和記憶體使用

CPU使用率: int GetProcessInfo::GetProcessNumber() { SYSTEM_INFO info; GetSystemInfo(&info); return (int)info.dwNumberOfProcessors; }

zabbix監控程序的CPU和記憶體用量

最近需要對公司產品的其中一個後臺介面的實體記憶體的實時佔用量和CPU使用量進行監控統計,使用的zabbix版本2.4.8,經查閱資料找到以下文章: ------------------------------------------ 轉帖正文分割線 ----------

linux下c語言獲取當前時間

keyword spa pre urn markdown view 技術分享 時間 tle 和時間有關的函數定義在頭文件”time.h”中 常用函數: time_t time(time_t *t); 函數說明:此函數會返回從公元 1970 年1 月1 日的UTC

c# WinFo判斷當前程序是否已經啟動或存在的幾種方式

UC 初始 檢測 geb 是否 ren 返回 inf nvi 第一種方式:利用Mutex互斥量實現同時只有一個進程實例在運行    static class Program { /// <summary>

20180821 Python學習筆記:如何獲取當前程序路徑

con awl tab style onf getcwd nbsp 為知筆記 想要 20180821 Python學習筆記:如何獲取當前程序路徑啟動的腳本的路徑為:D:\WORK\gitbase\ShenzhenHouseInfoCrawler\main.py當前腳本的路徑

C C++如何獲取當前系統時間

C庫中與系統時間相關的函式定義在<time.h>標頭檔案中, C++定義在<ctime>標頭檔案中。 一、time(time_t*)函式 函式定義如下: time_t time (time_t* timer);

C語言獲取當前編譯執行檔案(XXX.exe)檔名和目錄路徑

C語言獲取當前編譯執行檔案(XXX.exe)檔名和目錄路徑 vc2010編譯通過 #include<stdio.h> #include<string.h> #include<windows.h> #include<stdlib.h> int ma

C語言獲取當前時間(Linux環境下,VC6.0,Codeblock環境下通用)

在Linux環境下用C語言編寫程式獲取當前的時間只要呼叫其內部的函式即可。這些函式在 time.h 這個標頭檔案裡,第一個函式原型: ① time_t time(time_t *t),通過Linux的man也很方便能夠找到這個函式的相關說明: 在Linux環境的命令列模式中輸入 man 2 time即

C++中獲取當前時間並格式化輸出

1 #include <string> 2 #include <time.h> 3 using namespace std; 4 5 string getTime() 6 { 7 time_t timep; 8 time (&timep);

linux C語言獲取當前可執行程式的路徑及檔名 vs 獲取當前工作路徑

 獲取當前工作路徑: 標頭檔案:#include <unistd.h> 定義函式:char * getcwd(char * buf, size_t size); 函式說明:getcwd()會將當前的工作目錄絕對路徑複製到引數buf 所指的記憶體空間,引數size

C#下獲取當前總毫秒數的方法和程式碼

在.Net下DateTime.Ticks獲得的是個long型的時間整數,具體表示是至0001 年 1 月 1 日午夜 12:00:00 以來所經過時間以100納秒的數字。轉換為秒為Ticks/1000

c++ 如何獲取當前時間

void GetCurrentTime(){        struct tm t;   //tm結構指標        time_t now;  //宣告time_t型別變數        time(&now);      //獲取系統日期和時間        localti

C# WinForm獲取當前擁有焦點的控制元件 .

//API宣告:獲取當前焦點控制元件控制代碼       [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)] internal static extern IntPtr

C語言獲取當前的日期及時間

我們在寫C語言程式的時候,有的時候會用到讀取本機的時間和日期,怎麼做呢?其實很簡單的,下面簡單說一下:C語言中讀取系統時間的函式為time(),其函式原型為:#include <time.h>time_t time( time_t * ) ;time_t就是lon

用PHP函式memory_get_usage獲取當前PHP記憶體消耗量 .

用PHP函式memory_get_usage獲取當前PHP記憶體消耗量: PHP效能優化過程中避免不了需要獲取PHP記憶體消耗,使用memory_get_usage()函式可獲取當前的記憶體消耗情況,函式使用簡單,下面介紹下memory_get_usage()函式的用法與例項。 一,函式原型 int memo

Object-C獲取當前觸控點的座標位置

//當有一個或多個手指觸控事件在當前檢視或window窗體中響應 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { NSSet *allTouches = [event allTouc

C#中獲取當前時間,及處理時間(對時間進行加減)

1.獲取當前的時間,並將時間格式化成為字串   DateTime dt=Datetime.Now;   string str=dt.ToString();        //這是最直接的轉化方法   string str2=dt.ToString("yyy-MM-dd HH:mm:ss");2.獲取年、月、日

C語言獲取當前時間

作業系統提供了很多系統呼叫,既方便程式設計師程式設計,又提高了程式的可移植性。在介紹利用系統呼叫獲取當前時間之前,先辨析幾個基本的概念。API ,系統呼叫 ,封裝例程API只是一個函式定義。系統呼叫通過軟中斷向核心發出一個明確的請求。Libc庫定義了一些API引用的封裝例程,