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

通过文件路径获取设备物理块大小失败:ioctl调用报不恰当设备错误

解决通过挂载点调用BLKPBSZGET ioctl失败的问题

问题原因

BLKPBSZGET 是块设备专属的ioctl命令,仅能作用于块设备节点(如 /dev/sdc)的文件描述符。你打开的是挂载点目录 /tmp,该文件描述符对应的是文件系统层对象,而非底层块设备,因此这类针对块设备的ioctl不被支持,触发 Inappropriate ioctl for device 错误。

解决方案

要获取挂载点对应设备的物理块大小,需先找到挂载点关联的块设备路径,再打开该块设备文件执行ioctl。

步骤1:获取挂载点对应的块设备路径

可通过解析 /proc/mounts 文件实现,该文件记录了系统所有挂载信息,从中匹配挂载点字段即可得到对应块设备路径。

步骤2:修正后的代码实现

以下代码先解析 /proc/mounts 找到块设备,再打开设备执行 BLKPBSZGET:

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <sys/ioctl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

// 从/proc/mounts中提取挂载点对应的块设备路径
int get_block_device_for_mount(const char *mount_point, char *dev_path, size_t dev_path_len) {
    FILE *fp = fopen("/proc/mounts", "r");
    if (!fp) {
        fprintf(stderr, "Failed to open /proc/mounts: %s\n", strerror(errno));
        return -1;
    }

    char line[1024];
    while (fgets(line, sizeof(line), fp)) {
        char dev[256], mount[256];
        // 解析每行:设备路径 挂载点 其余字段
        if (sscanf(line, "%255s %255s", dev, mount) != 2) {
            continue;
        }
        // 匹配目标挂载点
        if (strcmp(mount, mount_point) == 0) {
            strncpy(dev_path, dev, dev_path_len - 1);
            dev_path[dev_path_len - 1] = '\0';
            fclose(fp);
            return 0;
        }
    }

    fprintf(stderr, "No block device found for mount point: %s\n", mount_point);
    fclose(fp);
    return -1;
}

int main() {
    const char *mount_point = "/tmp";
    char dev_path[256];

    // 获取块设备路径
    if (get_block_device_for_mount(mount_point, dev_path, sizeof(dev_path)) != 0) {
        return EXIT_FAILURE;
    }

    // 打开块设备文件(需root权限,执行时加sudo)
    const int fd = open(dev_path, O_RDONLY);
    if (fd == -1) {
        fprintf(stderr, "Failed to open block device %s: %s\n", dev_path, strerror(errno));
        return EXIT_FAILURE;
    }

    unsigned long pbsz = 0;
    if (ioctl(fd, BLKPBSZGET, &pbsz) == -1) {
        fprintf(stderr, "ioctl BLKPBSZGET failed: %s\n", strerror(errno));
        close(fd);
        return EXIT_FAILURE;
    }

    printf("Physical block size for %s (mounted at %s): %lu\n", dev_path, mount_point, pbsz);

    close(fd);
    return EXIT_SUCCESS;
}

注意事项

  • 执行程序时需要root权限(前缀加sudo),因为块设备文件通常仅对root开放访问权限。
  • 若挂载点为绑定挂载、tmpfs等特殊类型,需根据场景调整解析逻辑,常规磁盘挂载场景下上述代码可正常工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 21:07:10