Windows Driver Samples剖析之Echo (三)

        本文还是遵循”由表入里“的原则,先讲解Echo工程中的”echoapp“,从与驱动交互的应用程序入手逐步了解驱动程序的机制。

一、程序流程

        如下图,该程序先通过”GetDevicePath“函数,使用与驱动绑定(共用Public.h文件)的GUID,去注册表中获取”设备的符号名“(字符串)。然后调用”CreateFile“函数,通过该符号名打开设备,获得设备句柄。拿到设备句柄后,就可以进行读写操作。

        该程序演示了”同步“和”异步“两种读写操作测试。其中,”异步读写“是将读写操作放到不同的线程中,并发执行。




二、关键函数

1,GetDeviePath

        GetDevicePath的功能就是通过”驱动程序的GUID“,去查询注册表,获取”设备的符号链接“,它是应用程序可识别的设备路径(可自行google"设备链接和设备名”)。摘要如下:

————————————————————————————————

        windows下的设备是以"\Device\[设备名]”形式命名的。例如磁盘分区的c盘,d盘的设备名称就是
"\Device\HarddiskVolume1”,"\Device\HarddiskVolume2”。当然也可以不指定设备名称,I/O管理器会自动分配一个数字作为设备的名称。例如"\Device\00000001"。
        \Device\[设备名],不容易记忆,通常符号链接可以理解为设备的别名,更重要的是设备名,只能被内核模式下的其他驱动所识别,而别名可以被用户模式下的应用程序识别,例如c盘,就是名为"c:"的符号链接,其真正的设备对象是"\Device\HarddiskVolume1”。
        驱动中符号链接名是这样写的: L"\\??\\HelloDDK" ---> \??\HelloDDK    或L"\\DosDevices\\HelloDDK" ---> \DosDevices\HelloDDK
        在应用程序中,符号链接名: L"\\\\.\\HelloDDK"-->\\.\HelloD

————————————————————————————————

        GetDevicePath通过两步获得设备链接,先调“CM_Get_Device_Interface_List_Size”获得路径字符串长度,开好空间,再调 “CM_Get_Device_Interface_List”函数获得路径。

         获得路径之后,还要判断是否有其他设备。主要是通过偏移,检测字符串是否为空来判断。代码如下:

<span style="font-size:14px;">    nextInterface = deviceInterfaceList + wcslen(deviceInterfaceList) + 1;
    if (*nextInterface != UNICODE_NULL) {
        printf("Warning: More than one device interface instance found. \n"
            "Selecting first matching device.\n\n");
    }</span>
<think>我们正在尝试解决在执行 `sudo bash echo $CUDA_HOME` 时出现的错误:`/usr/bin/echo: /usr/bin/echo:无法执行二进制文件`。这个错误通常意味着系统尝试执行一个二进制文件时遇到了问题,可能的原因包括路径错误、文件损坏、权限问题或架构不匹配。 根据用户提供的引用信息,我们可以得到一些线索: 引用[1]:提到了运行CUDA示例程序`deviceQuery`的步骤,这可以帮助我们验证CUDA安装。 引用[2]:说明了如何设置CUDA的环境变量,包括`PATH`和`LD_LIBRARY_PATH`。 引用[3]:解释了系统目录的结构和用途,特别是二进制文件存放的位置。 结合这些信息,我们分析问题并给出解决方案: 步骤1:理解命令的错误 用户执行的命令是:`sudo bash echo $CUDA_HOME` 这个命令的意思是:以root权限运行bash,并让bash执行`echo $CUDA_HOME`。但是,这里使用`bash`来执行`echo`命令的方式是不正确的。因为`echo`是shell内建命令,也可以是一个外部命令(通常在`/bin/echo`或`/usr/bin/echo`)。当使用`bash echo ...`时,bash会尝试将`echo`作为脚本文件来执行,而不是作为内建命令。因此,它会去寻找名为`echo`的脚本文件,如果找不到,可能会尝试执行二进制文件,但这里它找到了`/usr/bin/echo`(一个二进制文件),然后试图用bash去解释执行这个二进制文件,从而导致错误。 正确的做法应该是: 方法1:直接使用内建的echo(在终端中直接输入): echo $CUDA_HOME 方法2:如果要用sudo,应该使用: sudo bash -c 'echo $CUDA_HOME' 但是,用户可能设置了环境变量`CUDA_HOME`,并且想通过sudo来查看,但由于sudo的环境变量可能和当前用户不同,所以需要特别处理。 步骤2:检查环境变量`CUDA_HOME`是否设置 用户可能没有正确设置`CUDA_HOME`,或者设置在了当前用户的配置文件中,而sudo执行时不会继承当前用户的环境变量(除非使用`-E`选项)。 因此,我们建议用户先在自己的终端中(不加sudo)检查: echo $CUDA_HOME 如果输出为空,则说明没有设置,需要按照引用[2]的方法设置。 步骤3:正确设置环境变量 按照引用[2]的方法,将环境变量添加到`/etc/profile`中(这样对所有用户生效)或者用户自己的`~/.bashrc`中(对当前用户生效)。注意,如果添加到`/etc/profile`,需要使用sudo编辑。 例如,对于CUDA 9.0,可以这样添加: export PATH=/usr/local/cuda-9.0/bin${PATH:+:${PATH}} export LD_LIBRARY_PATH=/usr/local/cuda-9.0/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} 然后,执行`source /etc/profile`或重新登录使配置生效。 步骤4:验证CUDA安装 按照引用[1]的方法,运行CUDA示例程序`deviceQuery`来验证安装。如果能够成功运行,则说明CUDA安装正确。 步骤5:如果问题仍然存在,考虑其他可能 - 检查`/usr/bin/echo`的权限:`ls -l /usr/bin/echo`,确保有执行权限(通常为-rwxr-xr-x)。 - 检查文件是否损坏:可以尝试用其他命令(如`cat`)查看`/usr/bin/echo`的内容,如果乱码则可能损坏。 - 检查架构:使用`file /usr/bin/echo`查看文件类型,确保是当前系统可执行的格式(如x86-64)。 解决方案总结: 1. 不要使用`sudo bash echo ...`这样的命令,而是直接使用`echo $CUDA_HOME`或`sudo -E bash -c 'echo $CUDA_HOME'`(`-E`保留当前用户环境变量)。 2. 确保环境变量`CUDA_HOME`已经正确设置,并已生效。 3. 按照引用[2]设置环境变量,并确保CUDA的安装路径正确。 4. 运行`deviceQuery`示例程序验证CUDA安装。 下面我们给出具体的操作步骤: 步骤1:检查当前用户的环境变量 ```bash echo $CUDA_HOME ``` 如果输出为空,则进行设置(假设CUDA安装在`/usr/local/cuda-9.0`): ```bash # 对于当前用户,编辑~/.bashrc echo "export CUDA_HOME=/usr/local/cuda-9.0" >> ~/.bashrc echo "export PATH=\$CUDA_HOME/bin:\$PATH" >> ~/.bashrc echo "export LD_LIBRARY_PATH=\$CUDA_HOME/lib64:\$LD_LIBRARY_PATH" >> ~/.bashrc source ~/.bashrc ``` 步骤2:再次检查 ```bash echo $CUDA_HOME # 应该输出:/usr/local/cuda-9.0 ``` 步骤3:验证nvcc ```bash nvcc --version ``` 步骤4:如果需要在sudo下查看,可以使用: ```bash sudo -E bash -c 'echo $CUDA_HOME' ``` 注意:`-E`选项使得sudo保留当前用户的环境变量。 如果上述步骤后,直接执行`echo $CUDA_HOME`可以正确输出,但sudo方式仍然不行,可能是因为sudo的环境变量配置问题。此时,可以考虑在sudoers文件中设置`env_keep`,或者直接在root的配置文件中设置环境变量(不推荐,除非必要)。 如果问题仍未解决,请检查CUDA的安装路径是否正确,以及环境变量中是否包含必要的路径。 最后,我们提供一些常见问题的解决方法: 问题1:`/usr/bin/echo`无法执行二进制文件 - 可能该文件已损坏,可以尝试重新安装coreutils包: ```bash sudo apt-get install --reinstall coreutils ``` 问题2:环境变量设置后,在终端中生效,但在脚本中不生效 - 确保脚本中source了配置文件,或者使用绝对路径。 问题3:多版本CUDA切换 - 可以通过更新软链接来实现。例如,将`/usr/local/cuda`链接到所需版本。 生成的相关问题: 1. 如何设置环境变量以便在sudo命令中保留? 2. 如何安装多个版本的CUDA并切换? 3. 运行`deviceQuery`时出现错误如何解决? 4. 如何验证CUDA与显卡驱动的兼容性? 希望这些步骤能帮助用户解决问题。</think>### 解决 `echo $CUDA_HOME` 报错 "/usr/bin/echo: 无法执行二进制文件" #### 问题根源分析 1. **命令语法错误** `sudo bash echo $CUDA_HOME` 是无效语法: - `bash` 后应接脚本文件,而非命令 - 错误地将 `echo` 当作脚本文件执行,导致系统尝试执行 `/usr/bin/echo` 二进制文件 2. **环境变量路径问题** `$CUDA_HOME` 可能指向无效路径(如目录而非文件),或路径包含特殊字符[^2] 3. **权限问题** 即使使用 `sudo`,SELinux 或文件权限可能阻止执行[^1] --- ### 正确解决步骤 #### 1. 验证 CUDA 安装路径 ```bash # 检查标准安装路径 ls /usr/local/cuda* # 查看常见二进制文件位置 ls -l /usr/local/cuda/bin/nvcc ``` 若存在类似 `/usr/local/cuda-11.8` 的目录,说明 CUDA 已安装[^2] #### 2. 正确设置环境变量 ```bash # 临时设置(当前终端有效) export CUDA_HOME=/usr/local/cuda # 或您的实际路径如 /usr/local/cuda-12.1 export PATH=$CUDA_HOME/bin:$PATH # 永久设置(添加到 ~/.bashrc) echo "export CUDA_HOME=/usr/local/cuda" >> ~/.bashrc echo "export PATH=\$CUDA_HOME/bin:\$PATH" >> ~/.bashrc source ~/.bashrc ``` #### 3. 正确查询环境变量 ```bash # 方法1:直接使用 echo echo $CUDA_HOME # 方法2:通过 bash -c 执行 sudo bash -c 'echo $CUDA_HOME' ``` #### 4. 验证 CUDA 可用性 ```bash # 检查编译器版本 nvcc --version # 运行测试程序(参考引用[1]) cd /path/to/NVIDIA_CUDA_Samples/bin/x86_64/linux/release ./deviceQuery ``` 成功输出应包含 GPU 设备信息[^1] #### 5. 修复权限问题 ```bash # 添加执行权限 sudo chmod +x /usr/local/cuda/bin/* # 禁用 SELinux 临时保护 sudo setenforce 0 ``` --- ### 关键排查点 | 检查项 | 正确状态 | 修复命令 | |--------|----------|----------| | `CUDA_HOME` 路径 | 指向 `cuda-xx.x` 目录 | `export CUDA_HOME=/usr/local/cuda-12.1` | | `nvcc` 是否在 PATH | `/usr/local/cuda/bin/nvcc` 存在 | `export PATH=/usr/local/cuda/bin:$PATH` | | 示例程序是否可运行 | `./deviceQuery` 显示 GPU 信息 | 重新安装 CUDA Samples | > **重要提示**:若使用 `sudo` 时环境变量失效,需在 `sudo` 后添加 `-E` 保留环境: > `sudo -E bash -c 'echo $CUDA_HOME'` --- ### 验证成功案例 ```bash $ echo $CUDA_HOME /usr/local/cuda-12.1 $ nvcc --version nvcc: NVIDIA (R) Cuda compiler driver Copyright (c) 2005-2023 NVIDIA Corporation Built on Wed_Nov_22_10:17:15_PST_2023 Cuda compilation tools, release 12.1, V12.1.105 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值