Golang如何获取Linux系统中每个进程的内存使用情况

Golang如何获取Linux系统中每个进程的内存使用情况 如何从proc文件夹读取每个进程及其使用的RAM内存,

7 回复

这与 Go 有什么关系?

更多关于Golang如何获取Linux系统中每个进程的内存使用情况的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我想使用Go语言读取Linux系统中每个正在运行的进程及其CPU使用率和内存使用情况

我无法从主函数获得所需的输出

哪个库提供 Unixprocess

结构体名称为Unixprocess。

type Unixprocess struct {
pid int
name string
ppid int
binary string
state rune
status string
pgrp  int
sid   int
meminfo *MemInfoStat
}
func (p *Unixprocess) fillFromStatus() error {
return p.fillFromStatusWithContext(context.Background())
}

func (p *Unixprocess) fillFromStatusWithContext(ctx context.Context) error {
pid := p.pid
statPath := memory.HostProc(strconv.Itoa(int(pid)), "status")
contents, err := ioutil.ReadFile(statPath)
if err != nil {
return err
}
lines := strings.Split(string(contents), "\n")

//p.memInfo = &MemoryInfoStat{}
 p.meminfo= &MemInfoStat{}
for _, line := range lines {
	tabParts := strings.SplitN(line, "\t", 2)
	if len(tabParts) < 2 {
		continue
	}
	value := tabParts[1]
	switch strings.TrimRight(tabParts[0], ":") {

	case "PPid", "Ppid":
		pval, err := strconv.ParseInt(value, 10, 32)
		if err != nil {
			return err
		}
		p.ppid = int(pval)

	case "VmRSS":
		value := strings.Trim(value, " kB") // remove last "kB"
		v, err := strconv.ParseUint(value, 10, 64)
		if err != nil {
			return err
		}
		p.meminfo.RSS=v* 1024
		//p.memInfo.RSS = v * 1024
	case "VmSize":
		value := strings.Trim(value, " kB") // remove last "kB"
		v, err := strconv.ParseUint(value, 10, 64)
		if err != nil {
			return err
		}
		p.meminfo.VMS = v * 1024
	case "VmSwap":
		value := strings.Trim(value, " kB") // remove last "kB"
		v, err := strconv.ParseUint(value, 10, 64)
		if err != nil {
			return err
		}
		p.meminfo.Swap = v * 1024
	}
	}

return nil
}

在Go语言中,可以通过读取Linux系统的/proc文件系统来获取每个进程的内存使用情况。/proc是一个虚拟文件系统,提供了内核和进程信息的实时访问。每个进程在/proc下有一个以进程ID(PID)命名的目录,其中status文件包含了内存使用数据。

以下是实现步骤和示例代码:

  1. 读取/proc目录,获取所有进程的PID。
  2. 对于每个PID,读取/proc/[PID]/status文件。
  3. 解析status文件中的VmRSS字段(表示实际使用的物理内存,单位通常是kB)。
  4. 可选地,将内存值转换为更友好的单位(如MB或GB)。

示例代码:

package main

import (
    "fmt"
    "io/ioutil"
    "os"
    "path/filepath"
    "strconv"
    "strings"
)

// 获取所有进程的PID列表
func getPIDs() ([]int, error) {
    var pids []int
    files, err := ioutil.ReadDir("/proc")
    if err != nil {
        return nil, err
    }
    for _, file := range files {
        if file.IsDir() {
            pid, err := strconv.Atoi(file.Name())
            if err == nil {
                pids = append(pids, pid)
            }
        }
    }
    return pids, nil
}

// 读取指定PID的status文件并解析VmRSS值
func getProcessMemory(pid int) (uint64, error) {
    statusPath := filepath.Join("/proc", strconv.Itoa(pid), "status")
    data, err := ioutil.ReadFile(statusPath)
    if err != nil {
        return 0, err
    }
    lines := strings.Split(string(data), "\n")
    for _, line := range lines {
        if strings.HasPrefix(line, "VmRSS:") {
            fields := strings.Fields(line)
            if len(fields) >= 2 {
                memKB, err := strconv.ParseUint(fields[1], 10, 64)
                if err != nil {
                    return 0, err
                }
                return memKB, nil // 返回单位为kB
            }
        }
    }
    return 0, fmt.Errorf("VmRSS not found for PID %d", pid)
}

func main() {
    pids, err := getPIDs()
    if err != nil {
        fmt.Printf("Error reading PIDs: %v\n", err)
        return
    }
    for _, pid := range pids {
        mem, err := getProcessMemory(pid)
        if err != nil {
            // 忽略无法读取的进程(如已终止)
            continue
        }
        // 转换为MB显示
        memMB := float64(mem) / 1024.0
        fmt.Printf("PID: %d, Memory Usage: %.2f MB\n", pid, memMB)
    }
}

代码说明:

  • getPIDs函数读取/proc目录,过滤出所有数字命名的目录(即PID)。
  • getProcessMemory函数读取指定PID的status文件,查找VmRSS行并解析其值(单位kB)。
  • 主函数遍历所有PID,获取内存使用并输出为MB。

注意:

  • 某些进程可能无法访问(如权限不足或进程已终止),代码中通过continue跳过错误。
  • VmRSS表示实际驻留内存,是进程使用的物理内存部分,不包括交换空间。
  • 内存值以kB为单位,示例中转换为MB以便于阅读。

运行此代码需要Linux环境,并可能需要root权限以访问所有进程信息。输出示例如下:

PID: 1, Memory Usage: 8.50 MB
PID: 2, Memory Usage: 0.00 MB
...
回到顶部