LINUX.ORG.RU

Какой самый быстрый способ прочитать значение из файла

 ,


0

2

Всем привет!

Допустим у меня есть файлы содержащие одно единственное значение, например md5 другого файла, или файл '/sys/class/power_supply/battery/online', который содержит только 0 или 1 в зависимости от состояния устройства...

Какой самый простой и правильный способ получить эти значения в программе?

Например я сейчас читаю значение таким образом, но мне не нравится как это выглядит...

static int
battery_online () {
    FILE *f = fopen ("/sys/class/power_supply/battery/online", "r");
    if (!f) {
        perrmsg ("fopen: '/sys/class/power_supply/battery/online'");
        return 0;
    }

    char str[32];
    int status = 0;
    if (fgets (str, sizeof (str), f))
        status = atoi (str);
    else
        perrmsg ("fail on read '/sys/class/power_supply/battery/online'");
    fclose (f);
    return status;
}

Покритикуйте? Как правильней сделать? Спасибо)

Ответ на: комментарий от mittorn

по идее эти виртуальные файлы не должны запоминать позицию

Нет, они обязаны запоминать позицию, иначе семантика файлов поломается.

выполнять read

Можно вызывать pread() вместо lseek()+read().

i-rinat ★★★★★ ()
Ответ на: комментарий от i-rinat

ну так надо смотреть реализацию в ядре. семанитика файлов на уровне реализации в драйвере этих самых read, write. Причём реализация твм максимально простая. Оно обязано разве что не выйти за границы буффера. уверен, что seek на таком файле выдаст ошибку.

mittorn ★★★★★ ()
Последнее исправление: mittorn (всего исправлений: 1)
#include <stdio.h>
#include <assert.h>

int batstat()
{
    char   stat = 0;
    FILE * file = NULL;
    assert(fopen("/sys/class/power_supply/battery/online","r"));
    fread(&stat, 1, 1, file);
    fclose(file);
    return (stat == '0');
}

int main(int argc, char *argv[])
{
    printf("%d\n",batstat());
    return 0;
}

А вообще код можно раздуть, первое не открывать и закрывать каждый раз файл, а открыть его в начале программы и закрыть в конце передавай в функцию указатель на файл это раз, саму функцию можно через pthread отделить в отдельный поток в котором в цикле будет неистово читать значения и возвращать в основной поток по указателю значения.

Deleted ()
Ответ на: комментарий от Deleted

А вообще код можно раздуть, первое не открывать и закрывать каждый раз файл, а открыть его в начале программы и закрыть в конце передавай в функцию указатель на файл это раз, саму функцию можно через pthread отделить в отдельный поток в котором в цикле будет неистово читать значения и возвращать в основной поток по указателю значения.

Если на деле эта функция вызывается раз в пять минут или ещё реже, то практического смысла в таких наваротах нет.

cPunk ★★ ()
Последнее исправление: cPunk (всего исправлений: 1)

Замени этой файл на fifo и читай из него только изменения. Вряд ли писатель заметит. Правда root нужен. И другие читатели могут поломаться.

Я так понял этот твой battery_online вызывается постоянно среди миллиарда других такого типа проверок, и поэтому ты ссышь из-за производительности?

Тогда вынеси открытие файла вовне. До пересоздания дескриптор вроде не меняется. И закрывать файл не нужно. Просто seek. И не вызывай в каждом цикле - отслеживай изменения (времени, например). И значение в int не нужно конвертить. Сравнивать на неравенство можно и строки. А в данном случае символы (их и нужно читать).

Ну и обычные оптимизации память -> скорость: сделай локальные переменные статическими.

anonymous ()

у меня есть файлы содержащие одно единственное значение, например md5 другого файла

Если постановка задачи допускает альтернативные варианты хранения, то можно попытаться сэкономить на спичахколичестве отдельных файлов, например положить хэш-суммы всех файлов в один список или sqlite-базу, или например поместить эти хэш-суммы в атрибуты файловой системы на файлах, к которым они относятся. Это может уменьшить количество операций чтения и повысить производительность

или файл '/sys/class/power_supply/battery/online'

С этими вообще не парься, тут нет обращений к файловой системе, и никакой «хитрый» способ чтения работать не будет, только системный вызов read и его всевозможные обертки типа fgets

annulen ★★★★★ ()
#define BATTERY_FILE_NAME "/sys/class/power_supply/battery/online"

static int
battery_online () {
    int status = 0;
    char c;
    int fd;

    fd = open (BATTERY_FILE_NAME, O_RDONLY);
    if (fd < 0) {
        perrmsg ("open: " BATTERY_FILE_NAME);
        return -1;
    }

    if (read(fd, &c, 1) != 1) {
        perrmsg ("fail on read " BATTERY_FILE_NAME);
        c = -1;
    } else {
        c -= '0';
        if (c != 0 && c != 1)
           c = -1;
    }

    close(fd);

    return c;
}
ttnl ★★★★★ ()
Последнее исправление: ttnl (всего исправлений: 3)
Ответ на: комментарий от Deleted

assert(fopen(«/sys/class/power_supply/battery/online»,«r»));

зачем мозг, assertдрочерство его заменит, в итоге прога ипанется только потому что на компе нет батареи... LOL

anonymous2 ★★★★ ()
Последнее исправление: anonymous2 (всего исправлений: 1)
Ответ на: комментарий от Deleted

сам подумай, что будет в продакшне дальше, если нет батареи...

и вообще читаешь fread ты из черной дыры если до сих пор и не понял...

сделать код красиво не означает правильно))

anonymous2 ★★★★ ()
Последнее исправление: anonymous2 (всего исправлений: 2)
Ответ на: комментарий от anonymous2

Я аще не программист, мне можно даже так! :D

подумай, что будет в продакшне дальше, если нет батареи…

#define NDEBUG )))))))))))

и вообще читаешь fread ты из черной дыры

Хм

Deleted ()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Deleted

вот твой код

FILE * file = NULL;
assert(fopen("/sys/class/power_supply/battery/online","r"));
fread(&stat, 1, 1, file);

неужели не понятно, креш будет ты при любых вариантах NDEBUG и assert абсолютно тут не информативен...

anonymous2 ★★★★ ()
Последнее исправление: anonymous2 (всего исправлений: 1)