sys_windows.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. //go:build windows
  2. // +build windows
  3. package sys
  4. import (
  5. "errors"
  6. "sync"
  7. "syscall"
  8. "unsafe"
  9. "github.com/shirou/gopsutil/v4/net"
  10. )
  11. // GetConnectionCount returns the number of active connections for the specified protocol ("tcp" or "udp").
  12. func GetConnectionCount(proto string) (int, error) {
  13. if proto != "tcp" && proto != "udp" {
  14. return 0, errors.New("invalid protocol")
  15. }
  16. stats, err := net.Connections(proto)
  17. if err != nil {
  18. return 0, err
  19. }
  20. return len(stats), nil
  21. }
  22. // GetTCPCount returns the number of active TCP connections.
  23. func GetTCPCount() (int, error) {
  24. return GetConnectionCount("tcp")
  25. }
  26. // GetUDPCount returns the number of active UDP connections.
  27. func GetUDPCount() (int, error) {
  28. return GetConnectionCount("udp")
  29. }
  30. // --- CPU Utilization (Windows native) ---
  31. var (
  32. modKernel32 = syscall.NewLazyDLL("kernel32.dll")
  33. procGetSystemTimes = modKernel32.NewProc("GetSystemTimes")
  34. cpuMu sync.Mutex
  35. lastIdle uint64
  36. lastKernel uint64
  37. lastUser uint64
  38. hasLast bool
  39. )
  40. type filetime struct {
  41. LowDateTime uint32
  42. HighDateTime uint32
  43. }
  44. // ftToUint64 converts a Windows FILETIME-like struct to a uint64 for
  45. // arithmetic and delta calculations used by CPUPercentRaw.
  46. func ftToUint64(ft filetime) uint64 {
  47. return (uint64(ft.HighDateTime) << 32) | uint64(ft.LowDateTime)
  48. }
  49. // CPUPercentRaw returns the instantaneous total CPU utilization percentage using
  50. // Windows GetSystemTimes across all logical processors. The first call returns 0
  51. // as it initializes the baseline. Subsequent calls compute deltas.
  52. func CPUPercentRaw() (float64, error) {
  53. var idleFT, kernelFT, userFT filetime
  54. r1, _, e1 := procGetSystemTimes.Call(
  55. uintptr(unsafe.Pointer(&idleFT)),
  56. uintptr(unsafe.Pointer(&kernelFT)),
  57. uintptr(unsafe.Pointer(&userFT)),
  58. )
  59. if r1 == 0 { // failure
  60. if e1 != nil {
  61. return 0, e1
  62. }
  63. return 0, syscall.GetLastError()
  64. }
  65. idle := ftToUint64(idleFT)
  66. kernel := ftToUint64(kernelFT)
  67. user := ftToUint64(userFT)
  68. cpuMu.Lock()
  69. defer cpuMu.Unlock()
  70. if !hasLast {
  71. lastIdle = idle
  72. lastKernel = kernel
  73. lastUser = user
  74. hasLast = true
  75. return 0, nil
  76. }
  77. idleDelta := idle - lastIdle
  78. kernelDelta := kernel - lastKernel
  79. userDelta := user - lastUser
  80. // Update for next call
  81. lastIdle = idle
  82. lastKernel = kernel
  83. lastUser = user
  84. total := kernelDelta + userDelta
  85. if total == 0 {
  86. return 0, nil
  87. }
  88. // On Windows, kernel time includes idle time; busy = total - idle
  89. busy := total - idleDelta
  90. pct := float64(busy) / float64(total) * 100.0
  91. // lower bound not needed; ratios of uint64 are non-negative
  92. if pct > 100 {
  93. pct = 100
  94. }
  95. return pct, nil
  96. }