3. NPU设备节点创建与权限配置

{'id' 学习卡片

任务说明

本案例目标是在Linux系统中为NPU设备正确创建设备节点,并配置适当的用户权限,使非root用户能够访问NPU设备。我们将以典型的NPU驱动(如RKNN、Haisi或通用加速器驱动)为例,完成从驱动加载到设备节点生成、权限设置的完整闭环。

实现方案

设备节点的创建通常由驱动在加载时通过miscdevice或字符设备框架自动完成,但有时需要手动创建(例如驱动未使用自动节点生成机制,或节点被误删)。本案例提供两种路径:路径A为驱动自动创建节点后的权限配置;路径B为手动创建设备节点并设置权限。两种路径均以/dev/npu作为目标设备节点。

代码实现

#!/bin/bash
# npu_device_setup.sh - NPU设备节点创建与权限配置

set -e

NPU_DEV_NAME="npu"
NPU_DEV_PATH="/dev/${NPU_DEV_NAME}"
NPU_MAJOR=${NPU_MAJOR:-10}        # 主设备号,按实际驱动填写
NPU_MINOR=${NPU_MINOR:-0}          # 次设备号
NPU_GROUP=${NPU_GROUP:-realtime}   # 允许访问的用户组
NPU_MODE=${NPU_MODE:-660}          # 设备节点权限

# 检查驱动是否已加载
check_driver() {
    if lsmod | grep -q "npu_drv"; then
        echo "[INFO] NPU驱动已加载"
        return 0
    else
        echo "[WARN] NPU驱动未加载,尝试加载..."
        modprobe npu_drv 2>/dev/null || {
            echo "[ERROR] 无法加载npu_drv模块,请检查驱动路径"
            exit 1
        }
        return 0
    fi
}

# 路径A:驱动已自动创建设备节点,仅配置权限
setup_permissions() {
    if [ -e "${NPU_DEV_PATH}" ]; then
        echo "[INFO] 设备节点已存在,配置权限..."
        chown root:${NPU_GROUP} "${NPU_DEV_PATH}"
        chmod ${NPU_MODE} "${NPU_DEV_PATH}"
        echo "[OK] 权限配置完成: ${NPU_DEV_PATH} (${NPU_MODE} root:${NPU_GROUP})"
        return 0
    fi
    return 1
}

# 路径B:手动创建设备节点
create_device_node() {
    echo "[INFO] 手动创建设备节点..."
    # 确保/dev目录存在
    [ -d /dev ] || mkdir -p /dev
    
    # 创建字符设备节点
    mknod "${NPU_DEV_PATH}" c ${NPU_MAJOR} ${NPU_MINOR}
    chown root:${NPU_GROUP} "${NPU_DEV_PATH}"
    chmod ${NPU_MODE} "${NPU_DEV_PATH}"
    echo "[OK] 设备节点创建并配置: ${NPU_DEV_PATH} (${NPU_MODE} root:${NPU_GROUP})"
}

# 验证设备节点
verify_node() {
    echo "[INFO] 验证设备节点..."
    if [ -c "${NPU_DEV_PATH}" ]; then
        echo "[OK] ${NPU_DEV_PATH} 是有效的字符设备"
        ls -l "${NPU_DEV_PATH}"
        return 0
    else
        echo "[ERROR] ${NPU_DEV_PATH} 不存在或不是字符设备"
        return 1
    fi
}

# 主流程
main() {
    # 检查是否root
    if [ "$(id -u)" -ne 0 ]; then
        echo "[ERROR] 请以root权限运行此脚本"
        exit 1
    fi
    
    check_driver
    
    # 先尝试路径A,若节点不存在则走路径B
    if ! setup_permissions; then
        create_device_node
    fi
    
    verify_node
    echo "[DONE] NPU设备节点配置完成"
}

main "$@"

使用说明

将上述脚本保存为npu_device_setup.sh,赋予执行权限后以root运行:

chmod +x npu_device_setup.sh
sudo ./npu_device_setup.sh

脚本执行前需根据实际驱动调整NPU_MAJOR和NPU_MINOR变量值(可通过cat /proc/devices查看驱动注册的主设备号)。若驱动使用动态设备号,建议优先使用路径A(驱动自动创建节点),仅当节点缺失时才使用路径B手动创建。

验证方法

执行脚本后,通过以下步骤验证配置是否成功:

  1. 检查设备节点存在且类型正确:ls -l /dev/npu,应显示crw-rw----开头的字符设备;
  2. 确认属组正确:stat -c "%U %G %a" /dev/npu,输出应为root realtime 660;
  3. 以非root用户测试访问权限:sudo -u ${普通用户} cat /dev/npu,若用户属于realtime组,应能打开设备(可能返回I/O错误,但不应出现Permission denied);
  4. 若设备节点缺失,可手动删除后重新运行脚本,验证路径B的自动创建功能:rm /dev/npu && sudo ./npu_device_setup.sh。

判定标准:设备节点存在、权限为660且属组为realtime,非root用户在组内可正常打开设备文件,即视为配置通过。

NPU设备节点创建与权限配置流程 驱动模块加载 modprobe npu_drv 驱动自动创建设备节点? (/dev/npu 是否存在) 路径A: 配置权限 chown root:realtime /dev/npu 是 路径B: 手动创建节点 mknod /dev/npu c 10 0 否 设置属组与权限 chown root:realtime chmod 660 /dev/npu 验证设备节点 ls -l /dev/npu 非root用户访问测试 sudo -u user cat /dev/npu 判定标准: 节点存在、权限660、属组realtime、非root可访问