687

私はかつて、実行中のアプリケーション内から次のパフォーマンスパラメータを決定するタスクを持っていました。

  • 使用可能な仮想メモリの合計
  • 現在使用されている仮想メモリ
  • プロセスで現在使用されている仮想メモリ
  • 使用可能なRAMの合計
  • 現在使用されているRAM
  • 私のプロセスで現在使用されているRAM
  • %現在使用されているCPU
  • %現在私のプロセスで使用されているCPU

コードはWindowsとLinuxで実行する必要がありました。これは標準的な作業のようですが、このトピックに関する情報が不完全/不正確/古くなっているため、マニュアル(WIN32 API、GNUドキュメント)やインターネットで必要な情報を見つけるのに数日かかりました。そこに見つかりました。

他の人が同じトラブルに巻き込まれるのを防ぐために、散らばった情報に加えて、試行錯誤で見つけた情報を一か所に集めておくといいと思いました。

4

10 に答える 10

736

ウィンドウズ

上記の値の一部は、適切な Win32 API から簡単に取得できます。完全を期すためにここにリストします。ただし、パフォーマンス データ ヘルパー ライブラリ (PDH) から取得する必要があるものもありますが、これは少し「直感的ではなく」、試行錯誤を繰り返して作業を行う必要があります。(少なくとも私はかなり時間がかかりました。おそらく私は少し愚かでした...)

注: 明確にするために、すべてのエラー チェックは次のコードから省略されています。リターンコードをチェックしてください...!

  • 合計仮想メモリ:

    #include "windows.h"
    
    MEMORYSTATUSEX memInfo;
    memInfo.dwLength = sizeof(MEMORYSTATUSEX);
    GlobalMemoryStatusEx(&memInfo);
    DWORDLONG totalVirtualMem = memInfo.ullTotalPageFile;
    

    注: 「TotalPageFile」という名前は、ここでは少し誤解を招きます。実際には、このパラメーターは「仮想メモリ サイズ」を示します。これは、スワップ ファイルとインストールされた RAM のサイズです。

  • 現在使用されている仮想メモリ:

    「仮想メモリの合計」と同じコード

     DWORDLONG virtualMemUsed = memInfo.ullTotalPageFile - memInfo.ullAvailPageFile;
    
  • 現在のプロセスで現在使用されている仮想メモリ:

    #include "windows.h"
    #include "psapi.h"
    
    PROCESS_MEMORY_COUNTERS_EX pmc;
    GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc));
    SIZE_T virtualMemUsedByMe = pmc.PrivateUsage;
    
  • 合計物理メモリ (RAM):

    「仮想メモリの合計」と同じコード

    DWORDLONG totalPhysMem = memInfo.ullTotalPhys;
    
  • 現在使用されている物理メモリ:

    「仮想メモリの合計」と同じコード

    DWORDLONG physMemUsed = memInfo.ullTotalPhys - memInfo.ullAvailPhys;
    
  • 現在のプロセスで現在使用されている物理メモリ:

    「現在のプロセスで現在使用されている仮想メモリ」と同じコード

    SIZE_T physMemUsedByMe = pmc.WorkingSetSize;
    
  • 現在使用中のCPU:

    #include "TCHAR.h"
    #include "pdh.h"
    
    static PDH_HQUERY cpuQuery;
    static PDH_HCOUNTER cpuTotal;
    
    void init(){
        PdhOpenQuery(NULL, NULL, &cpuQuery);
        // You can also use L"\\Processor(*)\\% Processor Time" and get individual CPU values with PdhGetFormattedCounterArray()
        PdhAddEnglishCounter(cpuQuery, L"\\Processor(_Total)\\% Processor Time", NULL, &cpuTotal);
        PdhCollectQueryData(cpuQuery);
    }
    
    double getCurrentValue(){
        PDH_FMT_COUNTERVALUE counterVal;
    
        PdhCollectQueryData(cpuQuery);
        PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal);
        return counterVal.doubleValue;
    }
    
  • 現在のプロセスで現在使用されている CPU:

    #include "windows.h"
    
    static ULARGE_INTEGER lastCPU, lastSysCPU, lastUserCPU;
    static int numProcessors;
    static HANDLE self;
    
    void init(){
        SYSTEM_INFO sysInfo;
        FILETIME ftime, fsys, fuser;
    
        GetSystemInfo(&sysInfo);
        numProcessors = sysInfo.dwNumberOfProcessors;
    
        GetSystemTimeAsFileTime(&ftime);
        memcpy(&lastCPU, &ftime, sizeof(FILETIME));
    
        self = GetCurrentProcess();
        GetProcessTimes(self, &ftime, &ftime, &fsys, &fuser);
        memcpy(&lastSysCPU, &fsys, sizeof(FILETIME));
        memcpy(&lastUserCPU, &fuser, sizeof(FILETIME));
    }
    
    double getCurrentValue(){
        FILETIME ftime, fsys, fuser;
        ULARGE_INTEGER now, sys, user;
        double percent;
    
        GetSystemTimeAsFileTime(&ftime);
        memcpy(&now, &ftime, sizeof(FILETIME));
    
        GetProcessTimes(self, &ftime, &ftime, &fsys, &fuser);
        memcpy(&sys, &fsys, sizeof(FILETIME));
        memcpy(&user, &fuser, sizeof(FILETIME));
        percent = (sys.QuadPart - lastSysCPU.QuadPart) +
            (user.QuadPart - lastUserCPU.QuadPart);
        percent /= (now.QuadPart - lastCPU.QuadPart);
        percent /= numProcessors;
        lastCPU = now;
        lastUserCPU = user;
        lastSysCPU = sys;
    
        return percent * 100;
    }
    

Linux

Linux では、最初は明白に思われた選択は、POSIX APIgetrusage()などを使用することでした。これを機能させるためにしばらく時間を費やしましたが、意味のある値は得られませんでした。最終的にカーネル ソース自体を確認したところ、どうやらこれらの API は Linux カーネル 2.6 の時点でまだ完全には実装されていないことがわかりました!?

最終的に、疑似ファイルシステム/procとカーネル呼び出しの読み取りを組み合わせて、すべての値を取得しました。

  • 合計仮想メモリ:

    #include "sys/types.h"
    #include "sys/sysinfo.h"
    
    struct sysinfo memInfo;
    
    sysinfo (&memInfo);
    long long totalVirtualMem = memInfo.totalram;
    //Add other values in next statement to avoid int overflow on right hand side...
    totalVirtualMem += memInfo.totalswap;
    totalVirtualMem *= memInfo.mem_unit;
    
  • 現在使用されている仮想メモリ:

    「仮想メモリの合計」と同じコード

    long long virtualMemUsed = memInfo.totalram - memInfo.freeram;
    //Add other values in next statement to avoid int overflow on right hand side...
    virtualMemUsed += memInfo.totalswap - memInfo.freeswap;
    virtualMemUsed *= memInfo.mem_unit;
    
  • 現在のプロセスで現在使用されている仮想メモリ:

    #include "stdlib.h"
    #include "stdio.h"
    #include "string.h"
    
    int parseLine(char* line){
        // This assumes that a digit will be found and the line ends in " Kb".
        int i = strlen(line);
        const char* p = line;
        while (*p <'0' || *p > '9') p++;
        line[i-3] = '\0';
        i = atoi(p);
        return i;
    }
    
    int getValue(){ //Note: this value is in KB!
        FILE* file = fopen("/proc/self/status", "r");
        int result = -1;
        char line[128];
    
        while (fgets(line, 128, file) != NULL){
            if (strncmp(line, "VmSize:", 7) == 0){
                result = parseLine(line);
                break;
            }
        }
        fclose(file);
        return result;
    }
    
  • 合計物理メモリ (RAM):

    「仮想メモリの合計」と同じコード

    long long totalPhysMem = memInfo.totalram;
    //Multiply in next statement to avoid int overflow on right hand side...
    totalPhysMem *= memInfo.mem_unit;
    
  • 現在使用されている物理メモリ:

    「仮想メモリの合計」と同じコード

    long long physMemUsed = memInfo.totalram - memInfo.freeram;
    //Multiply in next statement to avoid int overflow on right hand side...
    physMemUsed *= memInfo.mem_unit;
    
  • 現在のプロセスで現在使用されている物理メモリ:

    「現在のプロセスで現在使用されている仮想メモリ」の getValue() を次のように変更します。

    int getValue(){ //Note: this value is in KB!
        FILE* file = fopen("/proc/self/status", "r");
        int result = -1;
        char line[128];
    
        while (fgets(line, 128, file) != NULL){
            if (strncmp(line, "VmRSS:", 6) == 0){
                result = parseLine(line);
                break;
            }
        }
        fclose(file);
        return result;
    }
    

  • 現在使用中のCPU:

    #include "stdlib.h"
    #include "stdio.h"
    #include "string.h"
    
    static unsigned long long lastTotalUser, lastTotalUserLow, lastTotalSys, lastTotalIdle;
    
    void init(){
        FILE* file = fopen("/proc/stat", "r");
        fscanf(file, "cpu %llu %llu %llu %llu", &lastTotalUser, &lastTotalUserLow,
            &lastTotalSys, &lastTotalIdle);
        fclose(file);
    }
    
    double getCurrentValue(){
        double percent;
        FILE* file;
        unsigned long long totalUser, totalUserLow, totalSys, totalIdle, total;
    
        file = fopen("/proc/stat", "r");
        fscanf(file, "cpu %llu %llu %llu %llu", &totalUser, &totalUserLow,
            &totalSys, &totalIdle);
        fclose(file);
    
        if (totalUser < lastTotalUser || totalUserLow < lastTotalUserLow ||
            totalSys < lastTotalSys || totalIdle < lastTotalIdle){
            //Overflow detection. Just skip this value.
            percent = -1.0;
        }
        else{
            total = (totalUser - lastTotalUser) + (totalUserLow - lastTotalUserLow) +
                (totalSys - lastTotalSys);
            percent = total;
            total += (totalIdle - lastTotalIdle);
            percent /= total;
            percent *= 100;
        }
    
        lastTotalUser = totalUser;
        lastTotalUserLow = totalUserLow;
        lastTotalSys = totalSys;
        lastTotalIdle = totalIdle;
    
        return percent;
    }
    
  • 現在のプロセスで現在使用されている CPU:

    #include "stdlib.h"
    #include "stdio.h"
    #include "string.h"
    #include "sys/times.h"
    #include "sys/vtimes.h"
    
    static clock_t lastCPU, lastSysCPU, lastUserCPU;
    static int numProcessors;
    
    void init(){
        FILE* file;
        struct tms timeSample;
        char line[128];
    
        lastCPU = times(&timeSample);
        lastSysCPU = timeSample.tms_stime;
        lastUserCPU = timeSample.tms_utime;
    
        file = fopen("/proc/cpuinfo", "r");
        numProcessors = 0;
        while(fgets(line, 128, file) != NULL){
            if (strncmp(line, "processor", 9) == 0) numProcessors++;
        }
        fclose(file);
    }
    
    double getCurrentValue(){
        struct tms timeSample;
        clock_t now;
        double percent;
    
        now = times(&timeSample);
        if (now <= lastCPU || timeSample.tms_stime < lastSysCPU ||
            timeSample.tms_utime < lastUserCPU){
            //Overflow detection. Just skip this value.
            percent = -1.0;
        }
        else{
            percent = (timeSample.tms_stime - lastSysCPU) +
                (timeSample.tms_utime - lastUserCPU);
            percent /= (now - lastCPU);
            percent /= numProcessors;
            percent *= 100;
        }
        lastCPU = now;
        lastSysCPU = timeSample.tms_stime;
        lastUserCPU = timeSample.tms_utime;
    
        return percent;
    }
    

TODO: その他のプラットフォーム

/proc疑似ファイルシステムを読み取る部分を除いて、Linuxコードの一部はUnixでも機能すると思います。おそらく Unix では、これらの部分getrusage()を同様の機能に置き換えることができますか?

于 2008-09-15T15:55:30.560 に答える
152

Mac OS X

合計仮想メモリ

これは、Linuxのようなプリセットのスワップパーティションやファイルを使用しないため、MacOSXでは注意が必要です。Appleのドキュメントからのエントリは次のとおりです。

注:ほとんどのUnixベースのオペレーティングシステムとは異なり、MacOSXは仮想メモリに事前に割り当てられたスワップパーティションを使用しません。代わりに、マシンのブートパーティションで使用可能なすべてのスペースを使用します。

したがって、まだ使用可能な仮想メモリの量を知りたい場合は、ルートパーティションのサイズを取得する必要があります。あなたはこのようにそれを行うことができます:

struct statfs stats;
if (0 == statfs("/", &stats))
{
    myFreeSwap = (uint64_t)stats.f_bsize * stats.f_bfree;
}

現在使用されている仮想の合計

「vm.swapusage」キーを使用してsystclを呼び出すと、スワップの使用に関する興味深い情報が得られます。

sysctl -n vm.swapusage
vm.swapusage: total = 3072.00M  used = 2511.78M  free = 560.22M  (encrypted)

上記のセクションで説明したように、さらにスワップが必要な場合は、ここに表示されるスワップの合計使用量が変わる可能性があるわけではありません。したがって、合計は実際には現在のスワップの合計です。C ++では、このデータは次のように照会できます。

xsw_usage vmusage = {0};
size_t size = sizeof(vmusage);
if( sysctlbyname("vm.swapusage", &vmusage, &size, NULL, 0)!=0 )
{
   perror( "unable to get swap usage by calling sysctlbyname(\"vm.swapusage\",...)" );
}

sysctl.hで宣言されている「xsw_usage」は文書化されていないようであり、これらの値にアクセスするためのより移植性の高い方法があると思われることに注意してください。

プロセスで現在使用されている仮想メモリ

この関数を使用して、現在のプロセスに関する統計を取得できますtask_info。これには、プロセスの現在の常駐サイズと現在の仮想サイズが含まれます。

#include<mach/mach.h>

struct task_basic_info t_info;
mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;

if (KERN_SUCCESS != task_info(mach_task_self(),
                              TASK_BASIC_INFO, (task_info_t)&t_info,
                              &t_info_count))
{
    return -1;
}
// resident size is in t_info.resident_size;
// virtual size is in t_info.virtual_size;

使用可能なRAMの合計

システムで使用可能な物理RAMの量は、次のsysctlようなシステム機能を使用して使用できます。

#include <sys/types.h>
#include <sys/sysctl.h>
...
int mib[2];
int64_t physical_memory;
mib[0] = CTL_HW;
mib[1] = HW_MEMSIZE;
length = sizeof(int64_t);
sysctl(mib, 2, &physical_memory, &length, NULL, 0);

現在使用されているRAM

host_statisticsシステム関数から一般的なメモリ統計を取得できます。

#include <mach/vm_statistics.h>
#include <mach/mach_types.h>
#include <mach/mach_init.h>
#include <mach/mach_host.h>

int main(int argc, const char * argv[]) {
    vm_size_t page_size;
    mach_port_t mach_port;
    mach_msg_type_number_t count;
    vm_statistics64_data_t vm_stats;

    mach_port = mach_host_self();
    count = sizeof(vm_stats) / sizeof(natural_t);
    if (KERN_SUCCESS == host_page_size(mach_port, &page_size) &&
        KERN_SUCCESS == host_statistics64(mach_port, HOST_VM_INFO,
                                        (host_info64_t)&vm_stats, &count))
    {
        long long free_memory = (int64_t)vm_stats.free_count * (int64_t)page_size;

        long long used_memory = ((int64_t)vm_stats.active_count +
                                 (int64_t)vm_stats.inactive_count +
                                 (int64_t)vm_stats.wire_count) *  (int64_t)page_size;
        printf("free memory: %lld\nused memory: %lld\n", free_memory, used_memory);
    }

    return 0;
}

ここで注意すべきことの1つは、MacOSXには5種類のメモリページがあることです。それらは次のとおりです。

  1. 所定の位置にロックされ、スワップアウトできない有線ページ
  2. 物理メモリにロードされており、スワップアウトが比較的難しいアクティブなページ
  3. メモリにロードされているが、最近使用されておらず、まったく必要ない可能性がある非アクティブなページ。これらはスワッピングの潜在的な候補です。このメモリはおそらくフラッシュする必要があります。
  4. ある程度キャッシュされたキャッシュページで、簡単に再利用できる可能性があります。キャッシュされたメモリはおそらくフラッシュを必要としません。キャッシュされたページを再アクティブ化することは引き続き可能です
  5. 完全に無料ですぐに使用できる無料のページ。

Mac OS Xが実際の空きメモリをほとんど表示しないことがあるという理由だけで、急な通知でどれだけ使用できるかを示すのに適切でない場合があることに注意してください。

プロセスで現在使用されているRAM

上記の「プロセスで現在使用されている仮想メモリ」を参照してください。同じコードが適用されます。

于 2009-12-16T02:21:57.443 に答える
70

Linux

Linux では、この情報は /proc ファイル システムで利用できます。各 Linux ディストリビューションは、少なくとも 1 つの重要なファイルをカスタマイズしているように見えるため、私は使用されるテキスト ファイル形式の大ファンではありません。「ps」のソースをざっと見てみると、混乱が明らかになります。

しかし、あなたが探している情報を見つける場所はここにあります:

/proc/meminfoには、求めるシステム全体の情報の大部分が含まれています。ここでは、私のシステムのように見えます。MemTotalMemFreeSwapTotal、およびSwapFreeに興味があると思います。

Anderson cxc # more /proc/meminfo
MemTotal:      4083948 kB
MemFree:       2198520 kB
Buffers:         82080 kB
Cached:        1141460 kB
SwapCached:          0 kB
Active:        1137960 kB
Inactive:       608588 kB
HighTotal:     3276672 kB
HighFree:      1607744 kB
LowTotal:       807276 kB
LowFree:        590776 kB
SwapTotal:     2096440 kB
SwapFree:      2096440 kB
Dirty:              32 kB
Writeback:           0 kB
AnonPages:      523252 kB
Mapped:          93560 kB
Slab:            52880 kB
SReclaimable:    24652 kB
SUnreclaim:      28228 kB
PageTables:       2284 kB
NFS_Unstable:        0 kB
Bounce:              0 kB
CommitLimit:   4138412 kB
Committed_AS:  1845072 kB
VmallocTotal:   118776 kB
VmallocUsed:      3964 kB
VmallocChunk:   112860 kB
HugePages_Total:     0
HugePages_Free:      0
HugePages_Rsvd:      0
Hugepagesize:     2048 kB

CPU 使用率については、少し作業を行う必要があります。Linux では、システムの起動以降の全体的な CPU 使用率が利用可能になります。これはおそらくあなたが興味を持っているものではありません。最後の 1 秒間または 10 秒間の CPU 使用率を知りたい場合は、情報を照会して自分で計算する必要があります。

情報は/proc/statにあります。これはhttp://www.linuxhowtos.org/System/procstat.htmにかなり詳しく文書化されています。私の4コアボックスでは次のようになります。

Anderson cxc #  more /proc/stat
cpu  2329889 0 2364567 1063530460 9034 9463 96111 0
cpu0 572526 0 636532 265864398 2928 1621 6899 0
cpu1 590441 0 531079 265949732 4763 351 8522 0
cpu2 562983 0 645163 265796890 682 7490 71650 0
cpu3 603938 0 551790 265919440 660 0 9040 0
intr 37124247
ctxt 50795173133
btime 1218807985
processes 116889
procs_running 1
procs_blocked 0

まず、システムで使用できる CPU (またはプロセッサ、または処理コア) の数を決定する必要があります。これを行うには、「cpuN」エントリの数を数えます。ここで、N は 0 から始まり、増分します。cpuN 行の組み合わせである「cpu」行はカウントしないでください。私の例では、cpu0 から cpu3 まで、合計 4 つのプロセッサが表示されます。これからは、cpu0..cpu3 を無視して、「cpu」行だけに注目してください。

次に、これらの行の 4 番目の数値はアイドル時間の測定値であることを知っておく必要があります。したがって、「cpu」行の 4 番目の数値は、起動時以降のすべてのプロセッサの合計アイドル時間です。この時間は Linux の「jiffies」で測定され、1/100 秒です。

しかし、アイドル時間の合計は気にしません。最後の 1 秒など、特定の期間のアイドル時間を気にします。それを計算してください。このファイルを 1 秒間隔で 2 回読み取る必要があります。次に、行の 4 番目の値の diff を実行できます。たとえば、サンプルを取得して取得した場合:

cpu  2330047 0 2365006 1063853632 9035 9463 96114 0

次に、1 秒後に次のサンプルを取得します。

cpu  2330047 0 2365007 1063854028 9035 9463 96114 0

2 つの数値を引くと、差分が 396 になります。これは、CPU が最後の 1.00 秒のうち 3.96 秒アイドル状態だったことを意味します。もちろん、秘訣は、プロセッサの数で割る必要があることです。3.96 / 4 = 0.99、アイドル率があります。99% アイドル、1% ビジー。

私のコードでは、360 エントリのリング バッファがあり、このファイルを毎秒読み取ります。これにより、1 秒、10 秒などから 1 時間までの CPU 使用率をすばやく計算できます。

プロセス固有の情報については、/proc/pidを調べる必要があります。pid を気にしない場合は、/proc/self を調べることができます。

プロセスが使用する CPU は/proc/self/statで確認できます。これは、1 行で構成される奇妙に見えるファイルです。例えば:

19340 (whatever) S 19115 19115 3084 34816 19115 4202752 118200 607 0 0 770 384 2
 7 20 0 77 0 266764385 692477952 105074 4294967295 134512640 146462952 321468364
8 3214683328 4294960144 0 2147221247 268439552 1276 4294967295 0 0 17 0 0 0 0

ここで重要なデータは、13 番目と 14 番目のトークン (ここでは 0 と 770) です。13 番目のトークンはプロセスがユーザー モードで実行した jiffy の数であり、14 番目はプロセスがカーネル モードで実行した jiffy の数です。この 2 つを合計すると、合計 CPU 使用率が得られます。

繰り返しになりますが、プロセスの CPU 使用率を経時的に判断するには、このファイルを定期的にサンプリングし、差分を計算する必要があります。

編集: プロセスの CPU 使用率を計算するときは、1) プロセス内のスレッドの数、および 2) システム内のプロセッサの数を考慮する必要があることに注意してください。たとえば、シングルスレッド プロセスが CPU の 25% しか使用していない場合、それは良いことも悪いこともあります。シングル プロセッサ システムでは良好ですが、4 プロセッサ システムでは不十分です。これは、プロセスが常に実行されており、利用可能な CPU サイクルの 100% を使用していることを意味します。

プロセス固有のメモリ情報については、次のような /proc/self/status を確認する必要があります。

Name:   whatever
State:  S (sleeping)
Tgid:   19340
Pid:    19340
PPid:   19115
TracerPid:      0
Uid:    0       0       0       0
Gid:    0       0       0       0
FDSize: 256
Groups: 0 1 2 3 4 6 10 11 20 26 27
VmPeak:   676252 kB
VmSize:   651352 kB
VmLck:         0 kB
VmHWM:    420300 kB
VmRSS:    420296 kB
VmData:   581028 kB
VmStk:       112 kB
VmExe:     11672 kB
VmLib:     76608 kB
VmPTE:      1244 kB
Threads:        77
SigQ:   0/36864
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: fffffffe7ffbfeff
SigIgn: 0000000010001000
SigCgt: 20000001800004fc
CapInh: 0000000000000000
CapPrm: 00000000ffffffff
CapEff: 00000000fffffeff
Cpus_allowed:   0f
Mems_allowed:   1
voluntary_ctxt_switches:        6518
nonvoluntary_ctxt_switches:     6598

「Vm」で始まるエントリは興味深いものです。

  • VmPeakは、プロセスが使用する仮想メモリの最大容量 (kB (1024 バイト)) です。
  • VmSizeは、プロセスが現在使用している仮想メモリ空​​間 (kB) です。私の例では、かなり大きく、651,352 kB、つまり約 636 メガバイトです。
  • VmRssは、プロセスのアドレス空間にマップされたメモリの量、またはその常駐セット サイズです。これはかなり小さいです (420,296 kB、または約 410 メガバイト)。違い: 私のプログラムは mmap() を介して 636 MB をマップしましたが、そのうちの 410 MB しかアクセスしていないため、410 MB のページしか割り当てられていません。

よくわからない唯一の項目は、現在プロセスで使用されている Swapspace です。これが利用可能かどうかはわかりません。

于 2008-09-15T16:27:38.500 に答える
15

Windows では、以下のコードで CPU 使用率を取得できます。

#include <windows.h>
#include <stdio.h>

//------------------------------------------------------------------------------------------------------------------
// Prototype(s)...
//------------------------------------------------------------------------------------------------------------------
CHAR cpuusage(void);

//-----------------------------------------------------
typedef BOOL ( __stdcall * pfnGetSystemTimes)( LPFILETIME lpIdleTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime );
static pfnGetSystemTimes s_pfnGetSystemTimes = NULL;

static HMODULE s_hKernel = NULL;
//-----------------------------------------------------
void GetSystemTimesAddress()
{
    if(s_hKernel == NULL)
    {
        s_hKernel = LoadLibrary(L"Kernel32.dll");
        if(s_hKernel != NULL)
        {
            s_pfnGetSystemTimes = (pfnGetSystemTimes)GetProcAddress(s_hKernel, "GetSystemTimes");
            if(s_pfnGetSystemTimes == NULL)
            {
                FreeLibrary(s_hKernel);
                s_hKernel = NULL;
            }
        }
    }
}
//----------------------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------------------
// cpuusage(void)
// ==============
// Return a CHAR value in the range 0 - 100 representing actual CPU usage in percent.
//----------------------------------------------------------------------------------------------------------------
CHAR cpuusage()
{
    FILETIME               ft_sys_idle;
    FILETIME               ft_sys_kernel;
    FILETIME               ft_sys_user;

    ULARGE_INTEGER         ul_sys_idle;
    ULARGE_INTEGER         ul_sys_kernel;
    ULARGE_INTEGER         ul_sys_user;

    static ULARGE_INTEGER     ul_sys_idle_old;
    static ULARGE_INTEGER  ul_sys_kernel_old;
    static ULARGE_INTEGER  ul_sys_user_old;

    CHAR usage = 0;

    // We cannot directly use GetSystemTimes in the C language
    /* Add this line :: pfnGetSystemTimes */
    s_pfnGetSystemTimes(&ft_sys_idle,    /* System idle time */
        &ft_sys_kernel,  /* system kernel time */
        &ft_sys_user);   /* System user time */

    CopyMemory(&ul_sys_idle  , &ft_sys_idle  , sizeof(FILETIME)); // Could been optimized away...
    CopyMemory(&ul_sys_kernel, &ft_sys_kernel, sizeof(FILETIME)); // Could been optimized away...
    CopyMemory(&ul_sys_user  , &ft_sys_user  , sizeof(FILETIME)); // Could been optimized away...

    usage  =
        (
        (
        (
        (
        (ul_sys_kernel.QuadPart - ul_sys_kernel_old.QuadPart)+
        (ul_sys_user.QuadPart   - ul_sys_user_old.QuadPart)
        )
        -
        (ul_sys_idle.QuadPart-ul_sys_idle_old.QuadPart)
        )
        *
        (100)
        )
        /
        (
        (ul_sys_kernel.QuadPart - ul_sys_kernel_old.QuadPart)+
        (ul_sys_user.QuadPart   - ul_sys_user_old.QuadPart)
        )
        );

    ul_sys_idle_old.QuadPart   = ul_sys_idle.QuadPart;
    ul_sys_user_old.QuadPart   = ul_sys_user.QuadPart;
    ul_sys_kernel_old.QuadPart = ul_sys_kernel.QuadPart;

    return usage;
}


//------------------------------------------------------------------------------------------------------------------
// Entry point
//------------------------------------------------------------------------------------------------------------------
int main(void)
{
    int n;
    GetSystemTimesAddress();
    for(n=0; n<20; n++)
    {
        printf("CPU Usage: %3d%%\r", cpuusage());
        Sleep(2000);
    }
    printf("\n");
    return 0;
}
于 2012-12-19T07:11:35.720 に答える
15

Linux

A portable way of reading memory and load numbers is the sysinfo call

Usage

   #include <sys/sysinfo.h>

   int sysinfo(struct sysinfo *info);

DESCRIPTION

   Until Linux 2.3.16, sysinfo() used to return information in the
   following structure:

       struct sysinfo {
           long uptime;             /* Seconds since boot */
           unsigned long loads[3];  /* 1, 5, and 15 minute load averages */
           unsigned long totalram;  /* Total usable main memory size */
           unsigned long freeram;   /* Available memory size */
           unsigned long sharedram; /* Amount of shared memory */
           unsigned long bufferram; /* Memory used by buffers */
           unsigned long totalswap; /* Total swap space size */
           unsigned long freeswap;  /* swap space still available */
           unsigned short procs;    /* Number of current processes */
           char _f[22];             /* Pads structure to 64 bytes */
       };

   and the sizes were given in bytes.

   Since Linux 2.3.23 (i386), 2.3.48 (all architectures) the structure
   is:

       struct sysinfo {
           long uptime;             /* Seconds since boot */
           unsigned long loads[3];  /* 1, 5, and 15 minute load averages */
           unsigned long totalram;  /* Total usable main memory size */
           unsigned long freeram;   /* Available memory size */
           unsigned long sharedram; /* Amount of shared memory */
           unsigned long bufferram; /* Memory used by buffers */
           unsigned long totalswap; /* Total swap space size */
           unsigned long freeswap;  /* swap space still available */
           unsigned short procs;    /* Number of current processes */
           unsigned long totalhigh; /* Total high memory size */
           unsigned long freehigh;  /* Available high memory size */
           unsigned int mem_unit;   /* Memory unit size in bytes */
           char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding to 64 bytes */
       };

   and the sizes are given as multiples of mem_unit bytes.
于 2015-07-16T21:14:28.910 に答える
3

QNX

これは「コードのウィキページ」のようなものなので、QNX ナレッジ ベースからいくつかのコードを追加したいと思います (注: これは私の仕事ではありませんが、チェックしたところ、私のシステムでは問題なく動作します)。

CPU 使用率を % で取得する方法: http://www.qnx.com/support/knowledgebase.html?id=50130000000P9b5

#include <atomic.h>
#include <libc.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/iofunc.h>
#include <sys/neutrino.h>
#include <sys/resmgr.h>
#include <sys/syspage.h>
#include <unistd.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/debug.h>
#include <sys/procfs.h>
#include <sys/syspage.h>
#include <sys/neutrino.h>
#include <sys/time.h>
#include <time.h>
#include <fcntl.h>
#include <devctl.h>
#include <errno.h>

#define MAX_CPUS 32

static float Loads[MAX_CPUS];
static _uint64 LastSutime[MAX_CPUS];
static _uint64 LastNsec[MAX_CPUS];
static int ProcFd = -1;
static int NumCpus = 0;


int find_ncpus(void) {
    return NumCpus;
}

int get_cpu(int cpu) {
    int ret;
    ret = (int)Loads[ cpu % MAX_CPUS ];
    ret = max(0,ret);
    ret = min(100,ret);
    return( ret );
}

static _uint64 nanoseconds( void ) {
    _uint64 sec, usec;
    struct timeval tval;
    gettimeofday( &tval, NULL );
    sec = tval.tv_sec;
    usec = tval.tv_usec;
    return( ( ( sec * 1000000 ) + usec ) * 1000 );
}

int sample_cpus( void ) {
    int i;
    debug_thread_t debug_data;
    _uint64 current_nsec, sutime_delta, time_delta;
    memset( &debug_data, 0, sizeof( debug_data ) );
    
    for( i=0; i<NumCpus; i++ ) {
        /* Get the sutime of the idle thread #i+1 */
        debug_data.tid = i + 1;
        devctl( ProcFd, DCMD_PROC_TIDSTATUS,
        &debug_data, sizeof( debug_data ), NULL );
        /* Get the current time */
        current_nsec = nanoseconds();
        /* Get the deltas between now and the last samples */
        sutime_delta = debug_data.sutime - LastSutime[i];
        time_delta = current_nsec - LastNsec[i];
        /* Figure out the load */
        Loads[i] = 100.0 - ( (float)( sutime_delta * 100 ) / (float)time_delta );
        /* Flat out strange rounding issues. */
        if( Loads[i] < 0 ) {
            Loads[i] = 0;
        }
        /* Keep these for reference in the next cycle */
        LastNsec[i] = current_nsec;
        LastSutime[i] = debug_data.sutime;
    }
    return EOK;
}

int init_cpu( void ) {
    int i;
    debug_thread_t debug_data;
    memset( &debug_data, 0, sizeof( debug_data ) );
/* Open a connection to proc to talk over.*/
    ProcFd = open( "/proc/1/as", O_RDONLY );
    if( ProcFd == -1 ) {
        fprintf( stderr, "pload: Unable to access procnto: %s\n",strerror( errno ) );
        fflush( stderr );
        return -1;
    }
    i = fcntl(ProcFd,F_GETFD);
    if(i != -1){
        i |= FD_CLOEXEC;
        if(fcntl(ProcFd,F_SETFD,i) != -1){
            /* Grab this value */
            NumCpus = _syspage_ptr->num_cpu;
            /* Get a starting point for the comparisons */
            for( i=0; i<NumCpus; i++ ) {
                /*
                * the sutime of idle thread is how much
                * time that thread has been using, we can compare this
                * against how much time has passed to get an idea of the
                * load on the system.
                */
                debug_data.tid = i + 1;
                devctl( ProcFd, DCMD_PROC_TIDSTATUS, &debug_data, sizeof( debug_data ), NULL );
                LastSutime[i] = debug_data.sutime;
                LastNsec[i] = nanoseconds();
            }
            return(EOK);
        }
    }
    close(ProcFd);
    return(-1);
}

void close_cpu(void){
    if(ProcFd != -1){
        close(ProcFd);
        ProcFd = -1;
    }
}

int main(int argc, char* argv[]){
    int i,j;
    init_cpu();
    printf("System has: %d CPUs\n", NumCpus);
    for(i=0; i<20; i++) {
        sample_cpus();
        for(j=0; j<NumCpus;j++)
        printf("CPU #%d: %f\n", j, Loads[j]);
        sleep(1);
    }
    close_cpu();
}

空き (!) メモリを取得する方法: http://www.qnx.com/support/knowledgebase.html?id=50130000000mlbx

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <err.h>
#include <sys/stat.h>
#include <sys/types.h>

int main( int argc, char *argv[] ){
    struct stat statbuf;
    paddr_t freemem;
    stat( "/proc", &statbuf );
    freemem = (paddr_t)statbuf.st_size;
    printf( "Free memory: %d bytes\n", freemem );
    printf( "Free memory: %d KB\n", freemem / 1024 );
    printf( "Free memory: %d MB\n", freemem / ( 1024 * 1024 ) );
    return 0;
} 
于 2015-05-26T07:42:27.263 に答える
2

Mac OS X - CPU

全体的な CPU 使用率:

Mac OS X でシステム情報を取得するから:

#include <mach/mach_init.h>
#include <mach/mach_error.h>
#include <mach/mach_host.h>
#include <mach/vm_map.h>

static unsigned long long _previousTotalTicks = 0;
static unsigned long long _previousIdleTicks = 0;

// Returns 1.0f for "CPU fully pinned", 0.0f for "CPU idle", or somewhere in between
// You'll need to call this at regular intervals, since it measures the load between
// the previous call and the current one.
float GetCPULoad()
{
   host_cpu_load_info_data_t cpuinfo;
   mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
   if (host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&cpuinfo, &count) == KERN_SUCCESS)
   {
      unsigned long long totalTicks = 0;
      for(int i=0; i<CPU_STATE_MAX; i++) totalTicks += cpuinfo.cpu_ticks[i];
      return CalculateCPULoad(cpuinfo.cpu_ticks[CPU_STATE_IDLE], totalTicks);
   }
   else return -1.0f;
}

float CalculateCPULoad(unsigned long long idleTicks, unsigned long long totalTicks)
{
  unsigned long long totalTicksSinceLastTime = totalTicks-_previousTotalTicks;
  unsigned long long idleTicksSinceLastTime  = idleTicks-_previousIdleTicks;
  float ret = 1.0f-((totalTicksSinceLastTime > 0) ? ((float)idleTicksSinceLastTime)/totalTicksSinceLastTime : 0);
  _previousTotalTicks = totalTicks;
  _previousIdleTicks  = idleTicks;
  return ret;
}
于 2018-04-24T07:54:28.990 に答える
1

Linux の場合

/proc/self/statm を使用して、主要なプロセス メモリ情報を含む 1 行の数値を取得することもできます。これは、proc/self/status から取得するレポート情報の長いリストを調べるよりも処理が高速です。

proc(5)を参照

/proc/[pid]/statm

    Provides information about memory usage, measured in pages.
    The columns are:

        size       (1) total program size
                   (same as VmSize in /proc/[pid]/status)
        resident   (2) resident set size
                   (same as VmRSS in /proc/[pid]/status)
        shared     (3) number of resident shared pages (i.e., backed by a file)
                   (same as RssFile+RssShmem in /proc/[pid]/status)
        text       (4) text (code)
        lib        (5) library (unused since Linux 2.6; always 0)
        data       (6) data + stack
        dt         (7) dirty pages (unused since Linux 2.6; always 0)
于 2017-03-21T11:07:04.963 に答える