donet-core 使用C#获取CPU使用率、内存总量、可用容量、适用容量的获取(Linux/Windows)
linux-dash
A beautiful web dashboard for Linux
项目地址:https://gitcode.com/gh_mirrors/li/linux-dash
免费下载资源
·
usage:
SystemEnvironment.CPULOAD
SystemEnvironment.AvailablePhysicalMemory
SystemEnvironment.UsedPhysicalMemory
SystemEnvironment.TotalPhysicalMemory
SystemEnvironment.cs
namespace GVMServer.Ns.Deployment
{
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using GVMServer.DDD.Service;
using GVMServer.Net;
using GVMServer.Ns.Deployment.Os;
using GVMServer.Ns.Functional;
using Microsoft.Extensions.Configuration;
using Thread = System.Threading.Thread;
using Timer = GVMServer.Threading.Timer;
public class SystemEnvironment
{
private static readonly Stopwatch _getMemoryStatusWath = new Stopwatch();
private static MEMORY_INFO _memoryStatusInfo = new MEMORY_INFO();
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct MEMORY_INFO
{
public uint dwLength; // 当前结构体大小
public uint dwMemoryLoad; // 当前内存使用率
public long ullTotalPhys; // 总计物理内存大小
public long ullAvailPhys; // 可用物理内存大小
public long ullTotalPageFile; // 总计交换文件大小
public long ullAvailPageFile; // 总计交换文件大小
public long ullTotalVirtual; // 总计虚拟内存大小
public long ullAvailVirtual; // 可用虚拟内存大小
public long ullAvailExtendedVirtual; // 保留 这个值始终为0
}
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GlobalMemoryStatusEx(ref MEMORY_INFO mi);
private unsafe static MEMORY_INFO GetMemoryStatus()
{
lock (_getMemoryStatusWath)
{
if (!_getMemoryStatusWath.IsRunning || _getMemoryStatusWath.ElapsedMilliseconds >= 500)
{
_getMemoryStatusWath.Restart();
_memoryStatusInfo.dwLength = (uint)sizeof(MEMORY_INFO);
if (IsWindows())
{
GlobalMemoryStatusEx(ref _memoryStatusInfo);
}
else
{
CPULinuxLoadValue.GlobalMemoryStatus(ref _memoryStatusInfo);
}
}
return _memoryStatusInfo;
}
}
private static long g_llInOutNicBytesReceived = 0;
private static long g_llInOutNicBytesSent = 0;
private static Timer g_tmrPerSecondTickTimer = new Timer(1000);
private static NetworkInterface m_poInOutNetworkInterface = null;
private static string[] g_aoHostIPAddress;
private static ConcurrentDictionary<int, Stopwatch> m_poStopWatchTable = new ConcurrentDictionary<int, Stopwatch>();
static SystemEnvironment()
{
g_tmrPerSecondTickTimer.Tick += (sender, e) => OnTick(e);
g_tmrPerSecondTickTimer.Start();
OnTick(EventArgs.Empty);
}
protected static void OnTick(EventArgs e)
{
// 刷新当前出入流量网卡的信息
do
{
NetworkInterface poInOutNetworkInterface = QUERY_INOUT_NETWORK_INTERFACE();
if (m_poInOutNetworkInterface == null || m_poInOutNetworkInterface.Name != poInOutNetworkInterface?.Name)
{
IPInterfaceStatistics poIPInterfaceStatistics = poInOutNetworkInterface?.GetIPStatistics();
if (poIPInterfaceStatistics != null)
{
g_llInOutNicBytesReceived = poIPInterfaceStatistics.BytesReceived;
g_llInOutNicBytesSent = poIPInterfaceStatistics.BytesSent;
}
PerSecondBytesSent = 0;
PerSecondBytesReceived = 0;
}
else
{
IPInterfaceStatistics poIPInterfaceStatistics = poInOutNetworkInterface.GetIPStatistics();
if (poIPInterfaceStatistics != null)
{
PerSecondBytesSent = poIPInterfaceStatistics.BytesReceived - g_llInOutNicBytesReceived;
PerSecondBytesReceived = poIPInterfaceStatistics.BytesSent - g_llInOutNicBytesSent;
g_llInOutNicBytesReceived = poIPInterfaceStatistics.BytesReceived;
g_llInOutNicBytesSent = poIPInterfaceStatistics.BytesSent;
}
}
m_poInOutNetworkInterface = poInOutNetworkInterface;
} while (false);
// 刷新当前主机节点的网络链路畅通的数字地址
do
{
var aoHostIPAddress = SocketClient.GetActivityIPAddress().Select(i => i.ToString()).ToList();
var application = ServiceObjectContainer.Get<BaseApplication>();
if (application != null)
{
var s = application.GetConfiguration().GetSection("HostAddresses").Get<string[]>();
if (s != null && s.Length > 0)
{
int index = 0;
foreach (string i in s)
{
if (string.IsNullOrEmpty(i))
{
continue;
}
string x = i.TrimStart().TrimEnd();
if (string.IsNullOrEmpty(x))
{
continue;
}
aoHostIPAddress.Insert(index++, x);
}
}
}
g_aoHostIPAddress = aoHostIPAddress.ToArray();
} while (false);
if (IsWindows())
{
CPUWin32LoadValue.Refresh();
}
else
{
CPULinuxLoadValue.Refresh();
}
}
public unsafe static bool Equals(IPAddress x, IPAddress y)
{
if (x == null && y == null)
return true;
if (x.AddressFamily != y.AddressFamily)
return false;
byte[] bx = x.GetAddressBytes();
byte[] by = y.GetAddressBytes();
if (bx.Length != by.Length)
return false;
fixed (byte* pinnedX = bx)
{
fixed (byte* pinnedY = by)
{
if (bx.Length == 4)
return *(uint*)pinnedX == *(uint*)pinnedY; // 32bit
else if (bx.Length == 8)
return *(ulong*)pinnedX == *(ulong*)pinnedY; // 64bit
else if (bx.Length == 16)
return *(decimal*)pinnedX == *(decimal*)pinnedY; // 128bit
else if (bx.Length == 2)
return *(ushort*)pinnedX == *(ushort*)pinnedY; // 16bit
else if (bx.Length == 1)
return *pinnedX == *pinnedY;
else
{
for (int i = 0; i < bx.Length; ++i)
if (pinnedX[i] != pinnedY[i])
return false;
return true;
}
}
}
}
private static NetworkInterface QUERY_INOUT_NETWORK_INTERFACE()
{
return NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(ni =>
{
if (ni.NetworkInterfaceType != NetworkInterfaceType.Ethernet &&
ni.NetworkInterfaceType != NetworkInterfaceType.Wireless80211 &&
ni.NetworkInterfaceType != NetworkInterfaceType.Ppp) // PPPOE宽带拨号
{
return false;
}
if (ni.OperationalStatus != OperationalStatus.Up)
{
return false;
}
foreach (var addressInfo in ni.GetIPProperties().UnicastAddresses)
{
if (addressInfo.Address.AddressFamily != AddressFamily.InterNetwork)
{
continue;
}
if (Equals(addressInfo.Address, IPAddress.Any)
|| Equals(addressInfo.Address, IPAddress.None)
|| Equals(addressInfo.Address, IPAddress.Broadcast)
|| Equals(addressInfo.Address, IPAddress.Loopback))
{
continue;
}
if (IsWindows())
{
if (addressInfo.DuplicateAddressDetectionState == DuplicateAddressDetectionState.Preferred)
{
return true;
}
}
else
{
return true;
}
}
return false;
});
}
public static long PerSecondBytesSent { get; set; }
public static long PerSecondBytesReceived { get; set; }
public static double CPULOAD
{
get
{
if (IsWindows())
{
return CPUWin32LoadValue.CPULOAD;
}
return CPULinuxLoadValue.CPULOAD;
}
}
public static long AvailablePhysicalMemory => GetMemoryStatus().ullAvailPhys;
public static long UsedPhysicalMemory
{
get
{
MEMORY_INFO mi = GetMemoryStatus();
return (mi.ullTotalPhys - mi.ullAvailPhys);
}
}
public static bool IsWindows()
{
var platform = Environment.OSVersion.Platform;
return platform == PlatformID.Win32NT;
}
public static long TotalPhysicalMemory => GetMemoryStatus().ullTotalPhys;
public static long PrivateWorkingSet => Environment.WorkingSet;
public static int ProcessorCount => Environment.ProcessorCount;
public static string[] GetHostIPAddress() => g_aoHostIPAddress;
public static NetworkInterface GetInOutNetworkInterface() => m_poInOutNetworkInterface;
public static int ClockSleepTime(int maxConcurrent)
{
int intManagedThreadId = Thread.CurrentThread.ManagedThreadId;
lock (m_poStopWatchTable)
{
if (!m_poStopWatchTable.TryGetValue(intManagedThreadId, out Stopwatch poStopWatch) || poStopWatch == null)
{
poStopWatch = new Stopwatch();
poStopWatch.Start();
m_poStopWatchTable[intManagedThreadId] = poStopWatch;
}
long llElapsedWatchTicks = poStopWatch.ElapsedTicks;
double dblTotalMilliseconds = llElapsedWatchTicks / 10000.00;
if (dblTotalMilliseconds < 1)
{
return 0;
}
poStopWatch.Restart();
}
const double MAX_USE_LOAD = NsLoadbalancing.MAX_CPULOAD_ULTIMATE_NOT_EXCEEDING;
if (maxConcurrent <= 0)
{
return 0;
}
double dblUseLoad = SystemEnvironment.CPULOAD;
if (dblUseLoad < MAX_USE_LOAD) // 控制CPU利用率
{
return 0;
}
else
{
double dblAviLoad = unchecked(dblUseLoad - MAX_USE_LOAD);
double dblSleepTime = unchecked(dblAviLoad / maxConcurrent);
dblSleepTime = Math.Ceiling(dblSleepTime);
if (dblSleepTime < 1)
{
dblSleepTime = 1;
}
return unchecked((int)dblSleepTime);
}
}
}
}
CPUWin32LoadValue.cs
namespace GVMServer.Ns.Deployment.Os
{
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
static class CPUWin32LoadValue
{
private static ulong g_tsSysDeltaTime = 0;
private static ulong g_tsSysLastTime = 0;
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetProcessTimes(IntPtr hProcess, out FILETIME
lpCreationTime, out FILETIME lpExitTime, out FILETIME lpKernelTime,
out FILETIME lpUserTime);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern void GetSystemTimeAsFileTime(out FILETIME lpExitTime);
private static DateTime FiletimeToDateTime(FILETIME fileTime)
{
//NB! uint conversion must be done on both fields before ulong conversion
ulong hFT2 = unchecked((((ulong)(uint)fileTime.dwHighDateTime) << 32) | (uint)fileTime.dwLowDateTime);
return DateTime.FromFileTimeUtc((long)hFT2);
}
private static TimeSpan FiletimeToTimeSpan(FILETIME fileTime)
{
//NB! uint conversion must be done on both fields before ulong conversion
ulong hFT2 = unchecked((((ulong)(uint)fileTime.dwHighDateTime) << 32) |
(uint)fileTime.dwLowDateTime);
return TimeSpan.FromTicks((long)hFT2);
}
private static ulong FiletimeToUlong(FILETIME fileTime)
{
//NB! uint conversion must be done on both fields before ulong conversion
ulong hFT2 = unchecked((((ulong)(uint)fileTime.dwHighDateTime) << 32) |
(uint)fileTime.dwLowDateTime);
return hFT2;
}
private static double QUERY_CPULOAD()
{
if (!SystemEnvironment.IsWindows())
{
return 0;
}
GetSystemTimeAsFileTime(out FILETIME ftNow);
if (!GetProcessTimes(Process.GetCurrentProcess().Handle,
out FILETIME ftCreation,
out FILETIME ftExit,
out FILETIME ftKernel,
out FILETIME ftUser))
{
return 0;
}
ulong tsCpuUsageTime = (FiletimeToUlong(ftKernel) +
FiletimeToUlong(ftUser));
if (g_tsSysDeltaTime == 0)
{
g_tsSysDeltaTime = tsCpuUsageTime;
return 0;
}
ulong ftSystemNowTime = FiletimeToUlong(ftNow);
ulong tsSysTimeDelta = ftSystemNowTime - g_tsSysLastTime;
ulong tsSystemTimeDelta = tsCpuUsageTime - g_tsSysDeltaTime;
double cpu_load = (tsSystemTimeDelta * 100.00d + tsSysTimeDelta / 2.00d) / tsSysTimeDelta;
g_tsSysLastTime = ftSystemNowTime;
g_tsSysDeltaTime = tsCpuUsageTime;
cpu_load = cpu_load / Environment.ProcessorCount;
if (cpu_load < 0 ||
double.IsInfinity(cpu_load) ||
double.IsNaN(cpu_load) ||
double.IsNegativeInfinity(cpu_load) ||
double.IsPositiveInfinity(cpu_load))
{
cpu_load = 0;
}
return cpu_load;
}
public static double CPULOAD { get; private set; }
public static void Refresh() => CPULOAD = QUERY_CPULOAD();
}
}
CPULinuxLoadValue.cs
namespace GVMServer.Ns.Deployment.Os
{
using System;
using System.IO;
static class CPULinuxLoadValue
{
private static CPU_OCCUPY previous_cpu_occupy = null;
private static readonly object syncobj = new object();
private class CPU_OCCUPY
{
public string name;
public long user;
public long nice;
public long system;
public long idle;
public long lowait;
public long irq;
public long softirq;
}
public static double CPULOAD { get; private set; }
public static void Refresh()
{
CPULOAD = QUERY_CPULOAD();
}
private static double QUERY_CPULOAD(bool a = true)
{
lock (syncobj)
{
CPU_OCCUPY current_cpu_occupy = get_cpuoccupy();
if (current_cpu_occupy == null || previous_cpu_occupy == null)
{
previous_cpu_occupy = current_cpu_occupy;
return 0;
}
try
{
long od = (previous_cpu_occupy.user + previous_cpu_occupy.nice + previous_cpu_occupy.system + previous_cpu_occupy.idle + previous_cpu_occupy.lowait + previous_cpu_occupy.irq + previous_cpu_occupy.softirq);//第一次(用户+优先级+系统+空闲)的时间再赋给od
long nd = (current_cpu_occupy.user + current_cpu_occupy.nice + current_cpu_occupy.system + current_cpu_occupy.idle + current_cpu_occupy.lowait + current_cpu_occupy.irq + current_cpu_occupy.softirq);//第二次(用户+优先级+系统+空闲)的时间再赋给od
double sum = nd - od;
double idle = current_cpu_occupy.idle - previous_cpu_occupy.idle;
double cpu_use = idle / sum;
if (!a)
{
idle = current_cpu_occupy.user + current_cpu_occupy.system + current_cpu_occupy.nice - previous_cpu_occupy.user - previous_cpu_occupy.system - previous_cpu_occupy.nice;
cpu_use = idle / sum;
}
cpu_use = (cpu_use * 100) / Environment.ProcessorCount;
return cpu_use;
}
finally
{
previous_cpu_occupy = current_cpu_occupy;
}
}
}
private static string ReadArgumentValue(StreamReader sr)
{
string values = null;
if (sr != null)
{
while (!sr.EndOfStream)
{
char ch = (char)sr.Read();
if (ch == ' ')
{
if (values == null)
{
continue;
}
break;
}
values += ch;
}
}
return values;
}
private static long ReadArgumentValueInt64(StreamReader sr)
{
string s = ReadArgumentValue(sr);
if (string.IsNullOrEmpty(s))
{
return 0;
}
long r;
long.TryParse(s, out r);
return r;
}
private static CPU_OCCUPY get_cpuoccupy()
{
string path = "/proc/stat";
if (!File.Exists(path))
{
return null;
}
FileStream stat = null;
try
{
stat = File.OpenRead(path);
if (stat == null)
{
return null;
}
}
catch (Exception)
{
return null;
}
using (StreamReader sr = new StreamReader(stat))
{
CPU_OCCUPY occupy = new CPU_OCCUPY();
try
{
occupy.name = ReadArgumentValue(sr);
occupy.user = ReadArgumentValueInt64(sr);
occupy.nice = ReadArgumentValueInt64(sr);
occupy.system = ReadArgumentValueInt64(sr);
occupy.idle = ReadArgumentValueInt64(sr);
occupy.lowait = ReadArgumentValueInt64(sr);
occupy.irq = ReadArgumentValueInt64(sr);
occupy.softirq = ReadArgumentValueInt64(sr);
}
catch (Exception)
{
return null;
}
return occupy;
}
}
public static bool GlobalMemoryStatus(ref SystemEnvironment.MEMORY_INFO mi)
{
string path = "/proc/meminfo";
if (!File.Exists(path))
{
return false;
}
FileStream stat = null;
try
{
stat = File.OpenRead(path);
if (stat == null)
{
return false;
}
}
catch (Exception)
{
return false;
}
long? call(string line, string key)
{
int i = line.IndexOf(':');
if (i < 0)
{
return null;
}
string lk = line.Substring(0, i);
if (string.IsNullOrEmpty(lk))
{
return null;
}
if (lk != key)
{
return null;
}
line = line.Substring(i + 1).TrimStart();
if (string.IsNullOrEmpty(line))
{
return null;
}
string[] sp = line.Split(' ');
if (sp == null || sp.Length <= 0)
{
return null;
}
line = sp[0];
if (string.IsNullOrEmpty(line))
{
return null;
}
long.TryParse(line, out long n);
return n * 1024;
}
using (StreamReader sr = new StreamReader(stat))
{
try
{
int counts = 0;
string line = string.Empty;
while (counts < 2 && !string.IsNullOrEmpty(line = sr.ReadLine()))
{
long? value = call(line, "MemTotal");
if (value != null)
{
counts++;
mi.ullTotalPhys = value.Value;
continue;
}
value = call(line, "MemAvailable");
if (value != null)
{
counts++;
mi.ullAvailPhys = value.Value;
continue;
}
}
return true;
}
catch (Exception)
{
return false;
}
}
}
}
}
GitHub 加速计划 / li / linux-dash
6
1
下载
A beautiful web dashboard for Linux
最近提交(Master分支:3 个月前 )
186a802e
added ecosystem file for PM2 4 年前
5def40a3
Add host customization support for the NodeJS version 4 年前
更多推荐
已为社区贡献12条内容
所有评论(0)