简体   繁体   English

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

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

I am running an embedded software (written in C) on Linux kernel. 我正在Linux内核上运行嵌入式软件(用C编写)。 I need to create an alarm on my software that checks whether an SD card is mounted on, and also find out it's capacity. 我需要在软件上创建一个警报,以检查SD卡是否已安装,并确定其容量。 I can brainstorm three ideas: 我可以集思广益三个想法:

  1. I am thinking to read and parse the file /proc/mounts 我正在考虑读取和解析文件/proc/mounts

    and then, use regex and a bunch of string comparisons to check if any SD card present, or 然后,使用regex和一串字符串比较来检查是否存在SD卡,或者

  2. scan and check for preferable directory name under /mnt/ using dirent library. 使用dirent库扫描并检查/mnt/下的首选目录名称。

    Either way, I am not sure how I am going to get the memory usage on SD card, or 无论哪种方式,我都不确定如何获取SD卡上的内存使用率,或者

  3. I could use my software to run a shell script containing df command, outputting into a file, and then read it. 我可以使用我的软件运行包含df命令的shell脚本,输出到文件中,然后读取它。 It should tell me whether an SD card is present, where it is mounted on, and it's capacity. 它应该告诉我是否存在SD卡,其安装位置以及容量。

I am sure there are plenty of easy and straightforward ways to acquire this information and feed it into my software. 我确信有很多简单明了的方法来获取这些信息并将其输入到我的软件中。 Perhaps a nifty library call? 也许是一个不错的图书馆电话? I did some research and saw resources on fstab , <sys/mount.h> , don't think these will take me any further. 我做了一些研究,发现fstab资源<sys/mount.h> ,不要认为这些会使我更进一步。 Does anyone have any better ideas? 有谁有更好的主意吗?

I have used the statfs() system call to get the SD card capacity and usage. 我已经使用statfs()系统调用来获取SD卡的容量和使用情况。 As for detecting card presence, I have used stat() call to look for the preferable directory at /mnt/sd_card_dir where sd_card_dir is set during auto-mount configuration. 至于检测卡是否存在,我使用stat()调用在/mnt/sd_card_dirsd_card_dir首选目录,其中在自动挂载配置期间设置了sd_card_dir If it exists, the SD card is (most likely) present - because the sd_card_dir folder gets created automatically whenever the SD card is inserted. 如果存在,则SD卡(最有可能)存在-因为只要插入SD卡,就会自动创建sd_card_dir文件夹。 If you create partitions, they should appear as sub-directories of sd_card_dir . 如果创建分区,则它们应显示为sd_card_dir

Following libraries should be called: 应调用以下库:

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

Following function handles the detection and it needs to be called periodically - at least once per minute. 跟踪功能处理检测,需要定期调用-至少每分钟一次。 In my particular case, I have called this function every 10 sec as a low-priority task and attached to the software's main loop. 在我的特殊情况下,我每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;
}

I know that you didn't ask for code but here you go ( I really had fun writing it ). 我知道您没有要求输入代码,但是您可以开始编写代码了( 我真的很开心 )。

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

This will show you the devices and some information about them, also the size that you are very interested in. 这将向您显示设备以及有关它们的一些信息,以及您非常感兴趣的尺寸。

Note, that there is no need for them to be mounted. 请注意,不需要安装它们。

You can of course, find more information in other places. 您当然可以在其他地方找到更多信息。 Just check the appropriate directories and you will be able to get everything. 只需检查适当的目录,您将可以获取所有内容。 For instance, there is a file removable that tells you whether the device is removable, which I think will be very useful in your case. 例如,有一个可移动文件,告诉您设备是否可移动,我认为这对您的情况非常有用。

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

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