1
0

sys_windows.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. //go:build windows
  2. package sys
  3. import (
  4. "errors"
  5. "sync"
  6. "syscall"
  7. "unsafe"
  8. "github.com/shirou/gopsutil/v4/net"
  9. "golang.org/x/sys/windows"
  10. )
  11. var SIGUSR1 = syscall.Signal(0)
  12. // GetConnectionCount returns the number of active connections for the specified protocol ("tcp" or "udp").
  13. func GetConnectionCount(proto string) (int, error) {
  14. if proto != "tcp" && proto != "udp" {
  15. return 0, errors.New("invalid protocol")
  16. }
  17. stats, err := net.Connections(proto)
  18. if err != nil {
  19. return 0, err
  20. }
  21. return len(stats), nil
  22. }
  23. // GetTCPCount returns the number of active TCP connections.
  24. func GetTCPCount() (int, error) {
  25. return GetConnectionCount("tcp")
  26. }
  27. // GetUDPCount returns the number of active UDP connections.
  28. func GetUDPCount() (int, error) {
  29. return GetConnectionCount("udp")
  30. }
  31. // --- CPU Utilization (Windows native) ---
  32. var (
  33. // NewLazySystemDLL forces the load from %SystemRoot%\System32 so a
  34. // kernel32.dll planted next to the binary can't hijack the call.
  35. modKernel32 = windows.NewLazySystemDLL("kernel32.dll")
  36. procGetSystemTimes = modKernel32.NewProc("GetSystemTimes")
  37. cpuMu sync.Mutex
  38. lastIdle uint64
  39. lastKernel uint64
  40. lastUser uint64
  41. hasLast bool
  42. )
  43. func ftToUint64(ft windows.Filetime) uint64 {
  44. return (uint64(ft.HighDateTime) << 32) | uint64(ft.LowDateTime)
  45. }
  46. // CPUPercentRaw returns instantaneous total CPU utilization across all
  47. // logical processors via Windows GetSystemTimes. The first call returns 0
  48. // while it initializes the baseline; subsequent calls compute deltas.
  49. func CPUPercentRaw() (float64, error) {
  50. var idleFT, kernelFT, userFT windows.Filetime
  51. r1, _, e1 := procGetSystemTimes.Call(
  52. uintptr(unsafe.Pointer(&idleFT)),
  53. uintptr(unsafe.Pointer(&kernelFT)),
  54. uintptr(unsafe.Pointer(&userFT)),
  55. )
  56. if r1 == 0 {
  57. if errno, _ := e1.(syscall.Errno); errno != 0 {
  58. return 0, errno
  59. }
  60. return 0, errors.New("GetSystemTimes failed")
  61. }
  62. idle := ftToUint64(idleFT)
  63. kernel := ftToUint64(kernelFT)
  64. user := ftToUint64(userFT)
  65. cpuMu.Lock()
  66. defer cpuMu.Unlock()
  67. if !hasLast {
  68. lastIdle = idle
  69. lastKernel = kernel
  70. lastUser = user
  71. hasLast = true
  72. return 0, nil
  73. }
  74. idleDelta := idle - lastIdle
  75. kernelDelta := kernel - lastKernel
  76. userDelta := user - lastUser
  77. lastIdle = idle
  78. lastKernel = kernel
  79. lastUser = user
  80. total := kernelDelta + userDelta
  81. if total == 0 {
  82. return 0, nil
  83. }
  84. // kernel time includes idle on Windows; busy = total - idle
  85. busy := total - idleDelta
  86. pct := float64(busy) / float64(total) * 100.0
  87. if pct > 100 {
  88. pct = 100
  89. }
  90. return pct, nil
  91. }