繁体   English   中英

如何从Linux提取SD卡的mount和df信息?

[英]How to pull mount and df information for SD card from linux?

我正在Linux内核上运行嵌入式软件(用C编写)。 我需要在软件上创建一个警报,以检查SD卡是否已安装,并确定其容量。 我可以集思广益三个想法:

  1. 我正在考虑读取和解析文件/proc/mounts

    然后,使用regex和一串字符串比较来检查是否存在SD卡,或者

  2. 使用dirent库扫描并检查/mnt/下的首选目录名称。

    无论哪种方式,我都不确定如何获取SD卡上的内存使用率,或者

  3. 我可以使用我的软件运行包含df命令的shell脚本,输出到文件中,然后读取它。 它应该告诉我是否存在SD卡,其安装位置以及容量。

我确信有很多简单明了的方法来获取这些信息并将其输入到我的软件中。 也许是一个不错的图书馆电话? 我做了一些研究,发现fstab资源<sys/mount.h> ,不要认为这些会使我更进一步。 有谁有更好的主意吗?

我已经使用statfs()系统调用来获取SD卡的容量和使用情况。 至于检测卡是否存在,我使用stat()调用在/mnt/sd_card_dirsd_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;
}

我知道您没有要求输入代码,但是您可以开始编写代码了( 我真的很开心 )。

#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);
}

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM