Golang硬件检测与加载Linux内核模块指南

Golang硬件检测与加载Linux内核模块指南 你好,

我是这里的新手,也是Golang的初学者。之前测试过一些简单的脚本,现在正尝试将一些Linux shell命令转换为Golang。

目前我正在尝试通过检测和加载所需的内核模块来初始化硬件。

以下是一个bash示例,展示如何加载硬件所需的内核模块:

grep -h MODALIAS /sys/bus/*/devices/*/uevent | cut -d= -f2 | xargs /sbin/modprobe -abq 2> /dev/null

现在我尝试用Go实现这个功能,或者只是检测正确的网卡和硬盘驱动程序。这需要使用网络连接并挂载硬盘分区。


更多关于Golang硬件检测与加载Linux内核模块指南的实战教程也可以访问 https://www.itying.com/category-94-b0.html

6 回复

我还没有找到关于如何使用Go语言完成这项工作的示例,而且我发现现有的工具不支持所需的选项来实现它。

更多关于Golang硬件检测与加载Linux内核模块指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


已找到u-root。它包含modprobe。经过测试,运行良好。

但如何检测初始化硬件/加载模块所需的内核模块?

谢谢!我知道 ghw。目前它只能检测 GPU 驱动程序,但无法检测所有设备/NIC/HDD。

GitHub

头像

paultag/go-modprobe

加载和卸载内核模块。通过在GitHub上创建账户为paultag/go-modprobe开发做贡献。

我虽然没使用过这些东西,但你可以试试这个:

GitHub

jaypipes/ghw

头像

Golang硬件发现/检测库。通过在GitHub上创建账户来为jaypipes/ghw开发做贡献。

在Go中实现硬件检测和加载Linux内核模块,可以通过os/exec包执行系统命令,或者使用syscall包直接调用系统调用。以下是一个完整的示例,展示如何检测和加载所需的内核模块,并处理网络和硬盘相关的模块。

方法1:使用os/exec执行modprobe命令

这种方法直接调用系统的modprobe命令,类似于原始bash脚本的功能。

package main

import (
    "fmt"
    "os/exec"
    "strings"
)

func loadKernelModules() error {
    // 获取所有设备的MODALIAS
    cmd := exec.Command("grep", "-h", "MODALIAS", "/sys/bus/*/devices/*/uevent")
    output, err := cmd.Output()
    if err != nil {
        return fmt.Errorf("failed to grep MODALIAS: %v", err)
    }

    // 提取MODALIAS值
    aliases := strings.Split(strings.TrimSpace(string(output)), "\n")
    for _, alias := range aliases {
        parts := strings.Split(alias, "=")
        if len(parts) < 2 {
            continue
        }
        modalias := parts[1]

        // 使用modprobe加载模块
        modprobeCmd := exec.Command("modprobe", "-abq", modalias)
        if err := modprobeCmd.Run(); err != nil {
            // 忽略错误,因为某些模块可能已加载或不存在
            fmt.Printf("modprobe failed for %s: %v\n", modalias, err)
        } else {
            fmt.Printf("Loaded module for alias: %s\n", modalias)
        }
    }
    return nil
}

func main() {
    if err := loadKernelModules(); err != nil {
        fmt.Printf("Error: %v\n", err)
    }
}

方法2:手动解析设备并加载特定模块

针对网卡和硬盘驱动,可以更精确地检测设备并加载对应的模块。以下示例展示如何检测网络接口和块设备,并加载相应的内核模块。

package main

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

// 检测网络接口并加载驱动
func loadNetworkDrivers() error {
    netPath := "/sys/class/net"
    devices, err := ioutil.ReadDir(netPath)
    if err != nil {
        return fmt.Errorf("failed to read network devices: %v", err)
    }

    for _, device := range devices {
        devicePath := filepath.Join(netPath, device.Name(), "device", "modalias")
        modalias, err := ioutil.ReadFile(devicePath)
        if err != nil {
            continue // 忽略无法读取modalias的设备
        }

        alias := strings.TrimSpace(string(modalias))
        if alias != "" {
            cmd := exec.Command("modprobe", "-abq", alias)
            if err := cmd.Run(); err != nil {
                fmt.Printf("Failed to load module for %s: %v\n", device.Name(), err)
            } else {
                fmt.Printf("Loaded network driver for %s\n", device.Name())
            }
        }
    }
    return nil
}

// 检测硬盘设备并加载驱动
func loadStorageDrivers() error {
    blockPath := "/sys/block"
    devices, err := ioutil.ReadDir(blockPath)
    if err != nil {
        return fmt.Errorf("failed to read block devices: %v", err)
    }

    for _, device := range devices {
        // 跳过虚拟设备(如loop、ram)
        if strings.HasPrefix(device.Name(), "loop") || strings.HasPrefix(device.Name(), "ram") {
            continue
        }

        devicePath := filepath.Join(blockPath, device.Name(), "device", "modalias")
        modalias, err := ioutil.ReadFile(devicePath)
        if err != nil {
            continue
        }

        alias := strings.TrimSpace(string(modalias))
        if alias != "" {
            cmd := exec.Command("modprobe", "-abq", alias)
            if err := cmd.Run(); err != nil {
                fmt.Printf("Failed to load module for %s: %v\n", device.Name(), err)
            } else {
                fmt.Printf("Loaded storage driver for %s\n", device.Name())
            }
        }
    }
    return nil
}

func main() {
    if err := loadNetworkDrivers(); err != nil {
        fmt.Printf("Network driver error: %v\n", err)
    }
    if err := loadStorageDrivers(); err != nil {
        fmt.Printf("Storage driver error: %v\n", err)
    }
}

说明:

  • 方法1 复制了原始bash脚本的行为,通过grepmodprobe加载所有检测到的模块。
  • 方法2 更针对性地处理网络和存储设备,通过读取/sys/class/net/sys/block目录下的modalias文件,并使用modprobe加载对应模块。
  • 错误处理被简化,某些模块加载失败是正常的(例如模块已加载或不存在)。
  • 需要以root权限运行这些代码,因为modprobe需要特权。

这些示例可以直接编译运行在Linux系统上,用于硬件初始化和模块加载。

回到顶部