單純的寫日誌,沒必要使用可變參數,但是不利於封裝,代碼難看,今天研究了一下可變參數
先查看手冊:http://www.cplusplus.com/reference/cstdio/vsprintf/?kw=vsprintf
function<cstdio>vsprintf
int vsprintf (char * s, const char * format, va_list arg );
Write formatted data from variable argument list to string
Composes a string with the same text that would be printed if format was used on printf, but using the elements in the variable argument list identified
by arg instead of additional function arguments and storing the resulting content as a C string in the buffer pointed by s.
Internally, the function retrieves arguments from the list identified by arg as if va_arg was used on it, and thus the state of arg is likely to
be altered by the call.
In any case, arg should have been initialized by va_start at some point before the call, and it is expected to be released by va_end at
some point after the call.
Parameters
-
s
-
Pointer to a buffer where the resulting C-string is stored.
The buffer should be large enough to contain the resulting string.
-
format
-
C string that contains a format string that follows the same specifications as
format in printf (see printf for
details).
-
arg
-
A value identifying a variable arguments list initialized with va_start.
va_list is a special type defined in <cstdarg>.
Return Value
On success, the total number of characters written is returned.
On failure, a negative number is returned.
Example
1234567891011121314151617181920212223242526272829
|
/* vsprintf example */#include <stdio.h>#include <stdarg.h>void PrintFError ( const char * format, ... ){ char buffer[256]; va_list args; va_start (args, format); vsprintf (buffer,format, args); perror (buffer); va_end (args);}int main (){ FILE * pFile; char szFileName[]="myfile.txt"; pFile = fopen (szFileName,"r"); if (pFile == NULL) PrintFError ("Error opening '%s'",szFileName); else { // file successfully open fclose (pFile); } return 0;}
|
In this example, if the file myfile.txt does not exist, perror is called to show an error message similar to:
Error opening file 'myfile.txt': No such file or directory |
概括起來就是: 可變參數定義時候,參數列表包含... va_list等提供支援。而va_list需要標頭檔<stdarg.h>. 上面代碼的va_start(args, format); 說,從fromat開始當做可變參數。 vsprintf(buffer, format, args); 說, 將format之後的可變參數轉化為一般字元串buffer。上面代碼直接printf(“%s", buffer); 得到的是 Error opening
file "myfile.txt". 很常規。 然後主函數調用中,將需要加入的變數,通過與printf類似的方式,加入。例如,需要加入兩個int參數 可以 function(”%d %d“, a, b); 依次類推。可變字串用起來很簡單。那麼其背後的原理呢? 可參見http://renjwjx.blog.51cto.com/811549/243827 也不難理解。。注意: log類在哪裡都可以用。 而記錄cpu資訊的程式運行在vs2005(之後版本應該也可以),因為vc6.0對psapi.h的支援不好,可以擷取cpu資訊,但是擷取不了記憶體及傳輸資料資訊。另外,要使用psapi需要windows sdk。如果發現運行不找不到psapi.h,那麼需要裝windows sdk。
1. 需要psapi.h 。 需要安裝windows sdk。 安裝完了之後發現,有的東西還是不能用。是因為sdk對vc6.0的支援不夠。後改用vs2005後解決。
2. sdk 環境的設定。 在include 和lib 目錄裡面分別設定psapi.h 和psapi.lib的路徑。比如:(vs2005)的路徑可以通過運行
的最後一個configuration 進行設定,當然也可以手工加入,效果如下:
還需要添加附加依賴項,或者直接#pragma
comment(lib, "Psapi.lib")
接下來寫我的log 類:
//mylog.h#ifndef MYLOG_H#define MYLOG_H#include <time.h>#include <stdio.h>#include <stdarg.h>class Mylog_{public:Mylog_::Mylog_(const char * logname) {logname_ = logname;FILE *fp = NULL; fp = fopen(logname_, "a+");fclose(fp);}Mylog_::~Mylog_(){if(fp != NULL)fclose(fp);}void Mylog_::writeLogTime(){fp = fopen(logname_, "a+");time(&rawtime);p = localtime(&rawtime);fprintf(fp, "%d/%d/%d ", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday);fprintf(fp, "%d:%d:%d", p->tm_hour, p->tm_min, p->tm_sec);fclose(fp);}void Mylog_::recordMessage ( const char * format, ... ){char buffer[256];va_list args;va_start (args, format);vsprintf (buffer,format, args);fp = fopen(logname_, "a+");fprintf(fp, "%s\n", buffer);fclose(fp);va_end (args);}public:const char * logname_;time_t rawtime;tm *p;FILE * fp;};#endif
為了得到cpu,記憶體資訊,還需要:
//process_stat.h#ifndef PROCESS_STAT_H#define PROCESS_STAT_H#include <windows.h>typedef LONG64 int64_t;typedef ULONG64 uint64_t;int get_cpu_usage(int pid);int get_memory_usage(int pid, uint64_t* mem, uint64_t* vmem);int get_io_bytes(int pid, uint64_t* read_bytes, uint64_t* write_byte);int GetPidFromName(LPCSTR lpProcessName);#endif
//代碼源自:http://www.rosoo.net/a/201112/15557.html 在此基礎上進行修改//process_stat_win.cpp#include <windows.h>#include <psapi.h>#include <assert.h>#include "process_stat.h"#include "process.h"#include "Tlhelp32.h"#include <string>using namespace std;//#define _WIN32_WINNT 0x0501#pragma comment(lib, "Psapi.lib")static uint64_t file_time_2_utc(const FILETIME* ftime){LARGE_INTEGER li;assert(ftime);li.LowPart = ftime->dwLowDateTime;li.HighPart = ftime->dwHighDateTime;return li.QuadPart;}static int get_processor_number(){SYSTEM_INFO info;GetSystemInfo(&info);return (int)info.dwNumberOfProcessors;}int get_cpu_usage(int pid){static int processor_count_ = -1;static int64_t last_time_ = 0;static int64_t last_system_time_ = 0;FILETIME now;FILETIME creation_time;FILETIME exit_time;FILETIME kernel_time;FILETIME user_time;int64_t system_time;int64_t time;int64_t system_time_delta;int64_t time_delta;int cpu = -1;if(processor_count_ == -1){processor_count_ = get_processor_number();}GetSystemTimeAsFileTime(&now);HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);//原來版本中,hProcess 為 GetCurrentProcess()if(!GetProcessTimes(hProcess, &creation_time,&exit_time,&kernel_time, &user_time)){return -1;}system_time = (file_time_2_utc(&kernel_time)+file_time_2_utc(&user_time)) / processor_count_;time = file_time_2_utc(&now);if((last_system_time_ == 0 ) || last_time_ == 0){last_system_time_ = system_time;last_time_ = time;return -1;}system_time_delta = system_time - last_system_time_;time_delta = time - last_time_;assert(time_delta != 0);if(time_delta == 0)return -1;cpu = (int) ((system_time_delta * 100 + time_delta / 2) / time_delta);last_system_time_ = system_time;last_time_ = time;return cpu;}int get_memory_usage(int pid, uint64_t* mem, uint64_t* vmem){PROCESS_MEMORY_COUNTERS pmc;HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);if(GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))){if(mem) *mem = pmc.WorkingSetSize;if(vmem) *vmem = pmc.PagefileUsage;return 0;}return -1;}int get_io_bytes(int pid, uint64_t* read_bytes, uint64_t* write_byte){IO_COUNTERS io_counter;HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);if(GetProcessIoCounters(hProcess, &io_counter)){if(read_bytes) *read_bytes = io_counter.ReadTransferCount;if(write_byte) *write_byte = io_counter.WriteTransferCount;return 0;}return -1;}/*void ReStartProcess(CString proname){bool isKill = KillProcessFromName(proname);if(isKill)printf("kill %s success\n", proname.GetBuffer(0));elseprintf("kill %s failed\n", proname.GetBuffer(0));CString strpath1;strpath1 = proname;Sleep(1000);CreateNewProcess(strpath1);Sleep(5000);int i = 1;while (FindProcessFromName(proname) == FALSE && i < 3){i++;CreateNewProcess(strpath1);Sleep(5000);}}BOOL CreateNewProcess(LPCSTR pszExeName){PROCESS_INFORMATION piProcInfoGPS;STARTUPINFO siStartupInfo;SECURITY_ATTRIBUTES saProcess, saThread;ZeroMemory( &siStartupInfo, sizeof(siStartupInfo) );siStartupInfo.cb = sizeof(siStartupInfo);saProcess.nLength = sizeof(saProcess);saProcess.lpSecurityDescriptor = NULL;saProcess.bInheritHandle = true;saThread.nLength = sizeof(saThread);saThread.lpSecurityDescriptor = NULL;saThread.bInheritHandle = true;return ::CreateProcess( NULL, (LPTSTR)pszExeName, &saProcess, &saThread, false,CREATE_DEFAULT_ERROR_MODE,NULL, NULL, &siStartupInfo, &piProcInfoGPS );}BOOL FindProcessFromName(LPCSTR lpProcessName){HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); PROCESSENTRY32 pe; pe.dwSize = sizeof(PROCESSENTRY32); if(!Process32First(hSnapShot,&pe)) { return FALSE; } CString strProcessName = lpProcessName; strProcessName.MakeLower(); while (Process32Next(hSnapShot,&pe)) { CString scTmp = pe.szExeFile; scTmp.MakeLower(); if(!scTmp.Compare(strProcessName)) { return TRUE; } scTmp.ReleaseBuffer(); } strProcessName.ReleaseBuffer(); return FALSE; }BOOL KillProcessFromName(LPCSTR lpProcessName){HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); PROCESSENTRY32 pe; pe.dwSize = sizeof(PROCESSENTRY32); if(!Process32First(hSnapShot,&pe)) { return FALSE; } CString strProcessName = lpProcessName; strProcessName.MakeLower(); while (Process32Next(hSnapShot,&pe)) { CString scTmp = pe.szExeFile; scTmp.MakeLower(); if(!scTmp.Compare(strProcessName)) { DWORD dwProcessID = pe.th32ProcessID; //獲得pidHANDLE hProcess = ::OpenProcess(PROCESS_TERMINATE,FALSE,dwProcessID); //不管通過pid還是進程名字最終都是為了獲得進程的控制代碼::TerminateProcess(hProcess,0); CloseHandle(hProcess); return TRUE; } scTmp.ReleaseBuffer(); } strProcessName.ReleaseBuffer(); return FALSE; }*/int GetPidFromName(LPCSTR lpProcessName){HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); PROCESSENTRY32 pe; pe.dwSize = sizeof(PROCESSENTRY32); if(!Process32First(hSnapShot,&pe)) { return FALSE; } //CString strProcessName = lpProcessName; string strProcessName(lpProcessName);//strProcessName.MakeLower(); while (Process32Next(hSnapShot,&pe)) { //這裡需要//CString scTmp = pe.szExeFile; char buffer[260];wcstombs(buffer, pe.szExeFile, sizeof(buffer));string scTmp(buffer);//scTmp.MakeLower(); if(!scTmp.compare(strProcessName)) { DWORD dwProcessID = pe.th32ProcessID; //獲得pidreturn dwProcessID;} } return -1; }
//main.cpp#include "process_stat.h"#include <windows.h>#include <stdio.h>#include "mylog.h"const char processName[] = "PlateSvr.exe";const char logName[] = "log1.txt";int main(){int pid = -1;pid = GetPidFromName(processName);if(pid == -1){printf("cann't find the process. please confirm the processName\n");return 0;}printf("processName = %s pid = %d\n", processName, pid);printf("正在記錄到%s", logName);while(1){int cpu;uint64_t mem, vmem, r, w;cpu = get_cpu_usage(pid);get_memory_usage(pid,&mem, &vmem);get_io_bytes(pid,&r, &w); //在本程式中沒用,在別的地方有用。。Mylog_ log(logName);log.writeLogTime();log.recordMessage("cpu: %d%%記憶體:%u KB\n", cpu, mem/1000);Sleep(1000); //記錄間隔}return 0;}
這些東西放在一起,應該是可以啟動並執行,如果不能運行,有可能是環境出了什麼問題。運行效果: