簡體   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