如何从linux中获取SD卡的mount和df信息?

问题描述 投票:1回答:2

我在Linux内核上运行嵌入式软件(用C语言编写)。我需要在我的软件上创建一个警报,检查是否安装了SD卡,并找出它的容量。我可以集体讨论三个想法:

  1. 我正在考虑阅读和解析文件/proc/mounts 然后,使用regex和一串字符串比较来检查是否存在任何SD卡,或者
  2. 使用/mnt/library扫描并检查dirent下的首选目录名称。 无论哪种方式,我不知道我将如何获得SD卡上的内存使用,或者
  3. 我可以使用我的软件运行包含df命令的shell脚本,输出到文件中,然后读取它。它应该告诉我SD卡是否存在,安装在哪里,以及它的容量。

我相信有很多简单直接的方法可以获取这些信息并将其输入我的软件。也许是一个漂亮的图书馆电话?我做了一些研究,并看到fstab<sys/mount.h>的资源,不要认为这些将带我进一步。有没有人有更好的想法?

c embedded-linux sd-card mount diskspace
2个回答
1
投票

我知道你没有要求代码但是你去了(我真的很开心写它)。

#include <stdio.h>

#include <dirent.h>
#include <limits.h>

#include <string.h>

#include <unistd.h>
#include <fcntl.h>

#include <stdlib.h>
#include <sys/stat.h>

static int
walkdir(const char *const path, int (*visit)(const char *const, const char *const), void *data)
{
    struct dirent *entry;
    DIR *dir;
    dir = opendir(path);
    if (dir == NULL)
        return -1;
    while ((entry = readdir(dir)) != NULL) {
        int code;
        code = visit(path, entry->d_name);
        if (code != 0) {
            closedir(dir);
            return code;
        }
    }
    closedir(dir);
    return 0;
}

static char *
file_get_content(const char *const path)
{
    int file;
    struct stat st;
    char *text;
    size_t size;

    text = NULL;
    file = -1;
    if (stat(path, &st) == -1)
        goto error;
    size = st.st_size;
    text = malloc(size + 1);
    if (text == NULL)
        goto error; // file too large, cannot read like this
    file = open(path, O_RDONLY);
    if (file == -1)
        goto error;
    if ((size = read(file, text, size)) <= 0)
        goto error;
    text[size] = '\0';
    if (file != -1)
        close(file);
    return text;
error:
    if (file != -1)
        close(file);
    free(text);
    return NULL;
}

static size_t
get_size(const char *const dirpath, const char *const name)
{
    char path[PATH_MAX];
    char *text;
    int length;
    size_t size;

    length = snprintf(path, sizeof(path), "%s/%s/size", dirpath, name);
    if (((size_t) length) > sizeof(path))
        return 0;
    size = 0;
    text = file_get_content(path);
    if (text != NULL) { 
        size = strtoll(text, NULL, 10);
        free(text);
    }
    return size;
}

static int
display_block(const char *const dirpath, const char *const name)
{
    const char *block;
    block = strrchr(dirpath, '/');
    if (block == NULL)
        return -1;
    block += 1;

    if (strstr(name, block) == name) {
        size_t size;
        // get_ the parition size
        //
        // Note, I had to divice the size by 2 because it didn't
        // match the sizes reported by `df'.
        //
        // Also, it appears that it's in megabytes 
        // (i.e. twice the size in MB)
        size = get_size(dirpath, name) / (1 << 21);
        // Display the result
        fprintf(stdout, "\tpartition: %s (%zu GB)\n", name, size);
    }

    return 0;
}

static char *
get_vendor(const char *const name)
{
    char path[PATH_MAX];
    int length;
    char *value;
    // get_ partitions
    length = snprintf(path, sizeof(path), "/sys/block/%s/device/vendor", name);
    if (((size_t) length) > sizeof(path))
        return NULL;
    value = file_get_content(path);
    if (value == NULL)
        return NULL;        
    // Make the trailing `\n' a '\0' instead
    strtok(value, "\n");
    return value;
}

static char *
get_model(const char *const name)
{
    char path[PATH_MAX];
    int length;
    char *value;
    // get_ partitions
    length = snprintf(path, sizeof(path), "/sys/block/%s/device/model", name);
    if (((size_t) length) > sizeof(path))
        return NULL;
    value = file_get_content(path);
    if (value == NULL)
        return NULL;        
    // Make the trailing `\n' a '\0' instead
    strtok(value, "\n");
    return value;
}

static int
parse_block(const char *const name)
{
    char path[PATH_MAX];
    int length;
    char *vendor;
    char *model;
    // get_ partitions
    length = snprintf(path, sizeof(path), "/sys/block/%s", name);
    if (((size_t) length) > sizeof(path))
        return -1;      
    vendor = get_vendor(name);
    model = get_model(name);    
    if ((model != NULL) && (vendor != NULL)) {
        fprintf(stdout, "block device: %s (%s %s)\n", name, vendor, model);
        walkdir(path, display_block, NULL);
    }
    free(vendor);
    free(model);
    return 0;
}

static int
list_devices(const char *const dirpath, const char *const name)
{
    if (*name == '.')
        return 0;
    parse_block(name);
    return 0;
}

int
main(void)
{
    return walkdir("/sys/block", list_devices, NULL);
}

这将向您显示设备和一些有关它们的信息,以及您非常感兴趣的尺寸。

请注意,不需要安装它们。

您当然可以在其他地方找到更多信息。只需检查相应的目录,您就可以获得所有内容。例如,有一个可移动文件告诉您该设备是否可移动,我认为这对您的情况非常有用。


1
投票

我使用statfs()系统调用来获取SD卡容量和使用情况。至于检测卡的存在,我使用stat()调用来查找/mnt/sd_card_dir的首选目录,其中sd_card_dir在自动安装配置期间设置。如果存在,则SD卡(很可能)存在 - 因为无论何时插入SD卡,都会自动创建sd_card_dir文件夹。如果创建分区,它们应显示为sd_card_dir的子目录。

应该调用以下库:

#include <sys/stat.h>
#include <sys/vfs.h>

以下功能处理检测,需要定期调用 - 至少每分钟调用一次。在我的特殊情况下,我每10秒调用一次此函数作为低优先级任务并附加到软件的主循环。

#define PATH "/mnt/sd_card_dir"
static int handler_sd_card_status(void)
{
    struct stat st;
    struct statfs fs;

    if (stat(PATH, &st))
        printf("Missing or unreadable\n");
    else {
        if (!statfs(PATH, &fs)) {
            char sd_stat[32];
            double scale = fs.f_bsize / 1e9;
            snprintf(sd_stat, sizeof(sd_stat),
                "%.2f of %.1f GB used",
                (fs.f_blocks - fs.f_bavail) * scale,
                fs.f_blocks * scale);
            printf("%s\n", sd_stat);
        } else
            printf("Size unreadable\n");
    }
    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.