You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派用C语言自动挂载USB及读取文件的路径问题求解

解决树莓派USB挂载与文件读取问题

问题分析

你遇到的核心问题出在挂载点逻辑与Linux自动挂载机制上:

  • 用/mnt/usb挂载失败:默认树莓派的/mnt目录下没有usb子目录,挂载命令要求目标目录必须存在才能执行。
  • 挂载到/media/user成功但找不到文件:/media/user是桌面环境自动挂载服务(udisks)的根目录,USB驱动器会被自动挂载到/media/user/[卷名]子目录中——你手动挂载到/media/user相当于覆盖了自动挂载的根目录,实际文件在自动生成的卷名子目录里,代码直接在/media/user下查找自然找不到。
  • 直接用/media/user/8.1 GB Volume当挂载点报错:这个目录是udisks自动创建的,手动挂载要求目标目录是预创建的空目录,且带空格的路径未转义会被shell解析为多个参数,导致"bad mount"错误。

解决方案

方案1:手动创建固定挂载点(推荐)

这是最稳定的方式,不受自动挂载服务干扰:

  1. 创建挂载目录并配置权限:
sudo mkdir -p /mnt/usb
sudo chown user:user /mnt/usb  # 将user替换为你的树莓派用户名
  1. 修改代码挂载点为/mnt/usb,同时修复挂载检查逻辑(原函数用strstr会误判包含该路径的其他挂载点)。

方案2:适配自动挂载路径

若想利用udisks自动挂载,需动态获取卷名对应的挂载路径:

  • 通过blkid命令获取USB驱动器UUID,在/etc/fstab中配置自动挂载到固定路径;或在代码中解析/proc/mounts,找到/dev/sda1对应的实际挂载点。

修改后的代码

以下是修复挂载检查逻辑、适配固定挂载点的完整代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

// 精确匹配挂载点,避免误判包含该路径的其他挂载项
bool isMounted(const char *mountPoint) {
    FILE *mountsFile = fopen("/proc/mounts", "r");
    if (mountsFile == NULL) {
        perror("Failed to open /proc/mounts");
        exit(EXIT_FAILURE);
    }

    char dev[64], mp[256], fs[64], opts[128];
    while (fscanf(mountsFile, "%s %s %s %s", dev, mp, fs, opts) != EOF) {
        if (strcmp(mp, mountPoint) == 0) {
            fclose(mountsFile);
            return true;
        }
    }

    fclose(mountsFile);
    return false;
}

int main() {
    const char *mountPoint = "/mnt/usb";  // 固定挂载点
    const char *usbDevice = "/dev/sda1";
    const char *fileName = "example.txt";

    // 挂载USB驱动器(未挂载时执行)
    if (!isMounted(mountPoint)) {
        char mountCommand[256];
        // 根据USB文件系统调整-t参数:vfat/ntfs-3g/ext4,ext4可省略
        snprintf(mountCommand, sizeof(mountCommand), "sudo mount -t vfat %s %s", usbDevice, mountPoint);
        int mountResult = system(mountCommand);
        if (mountResult != 0) {
            printf("Mount command failed with exit code %d\n", mountResult);
            return EXIT_FAILURE;
        }
    }

    // 确认挂载成功
    if (!isMounted(mountPoint)) {
        printf("Failed to mount the USB drive.\n");
        return EXIT_FAILURE;
    }

    // 拼接文件路径
    char filePath[256];
    snprintf(filePath, sizeof(filePath), "%s/%s", mountPoint, fileName);

    FILE *file = fopen(filePath, "r");
    if (file == NULL) {
        perror("Failed to open the file");  // 输出具体错误原因(如文件不存在/权限不足)
        // 尝试卸载挂载点
        char umountCommand[256];
        snprintf(umountCommand, sizeof(umountCommand), "sudo umount %s", mountPoint);
        system(umountCommand);
        return EXIT_FAILURE;
    }

    // 读取并打印文件内容
    char ch;
    while ((ch = fgetc(file)) != EOF) {
        printf("%c", ch);
    }
    printf("\n");

    fclose(file);

    // 卸载USB驱动器
    char umountCommand[256];
    snprintf(umountCommand, sizeof(umountCommand), "sudo umount %s", mountPoint);
    int umountResult = system(umountCommand);
    if (umountResult != 0) {
        printf("Unmount command failed with exit code %d\n", umountResult);
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

额外注意事项

  • 若USB是NTFS格式,需先安装ntfs-3g:sudo apt install ntfs-3g,并将代码中的-t vfat改为-t ntfs-3g。
  • 避免运行程序时输入sudo密码:通过sudo visudo添加一行user ALL=(ALL) NOPASSWD: /bin/mount, /bin/umount(替换user为你的用户名)。
  • 确认USB设备节点:用lsblk命令查看实际设备名(可能不是/dev/sda1)。

内容的提问来源于stack exchange,提问作者JRCastle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 06:24:58