реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Логирование данных в файл.
Jenya7
сообщение Mar 20 2018, 09:02
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



У меня по всему коду разбросанны сообщения типа
printf ("LIB ID = %d\n", lib_id);
сообщения выводятся серийно на терминал.

Сейчас нужно некоторые сообщения логировать в файл на SD карте.
Возникли вопросы по алгоритмике логирования данных
1. Прежде всего проверить есть ли место на SD - вопрос как это сделать? и если нет места? очистить файл и начать писать сначала?
2. Если файл открыт - добавить данные в файл, посмотреть флаг закрыть файл или нет.(я не хочу часто дергать файл - открывать\закрывать)
тогда что - держать глобальный указатель на файл?
3.Если файл закрыт - открыть с опцией "а+", добавить данные в файл, посмотреть флаг закрыть файл или нет.
Как вообще сделать покрасивше?
Go to the top of the page
 
+Quote Post
RobFPGA
сообщение Mar 20 2018, 09:43
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 214
Регистрация: 23-12-04
Пользователь №: 1 643



Приветствую!
Цитата(Jenya7 @ Mar 20 2018, 12:02) *
...
Как вообще сделать покрасивше?

Через очередь -
Пишете все логи в очередь сообщений, а в отдельном потоке выгребаете из нее и пишете туда куда надо и со всеми плюшками и шлю. наворотами sm.gif

Удачи! Rob.
Go to the top of the page
 
+Quote Post
HardEgor
сообщение Mar 20 2018, 09:48
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 223
Регистрация: 3-03-06
Из: Tomsk
Пользователь №: 14 925



Цитата(Jenya7 @ Mar 20 2018, 16:02) *
Сейчас нужно некоторые сообщения логировать в файл на SD карте.

1. писать мелкими файлами. например по 64кБ, как место кончилось -самый ранний стирать.
2. А если карту выдернут, или питание кончится, или перезагрузится контроллер? Если у вас FAT, то он очень не любит такие действия, придется карту нести на комп и восстанавливать таблицу.

Go to the top of the page
 
+Quote Post
haker_fox
сообщение Mar 20 2018, 10:01
Сообщение #4


Познающий...
******

Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125



QUOTE (Jenya7 @ Mar 20 2018, 17:02) *
1. Прежде всего проверить есть ли место на SD - вопрос как это сделать? и если нет места? очистить файл и начать писать сначала?

Проверить место. Если нет, стереть самый старый файл. Попутно об этом уведомить либо через терминал, либо в отдельный файл.
QUOTE (Jenya7 @ Mar 20 2018, 17:02) *
2. Если файл открыт - добавить данные в файл, посмотреть флаг закрыть файл или нет.(я не хочу часто дергать файл - открывать\закрывать)

Как-то так. Но аккуратно с многопоточностью.
QUOTE (Jenya7 @ Mar 20 2018, 17:02) *
Как вообще сделать покрасивше?

Как уже сказали выше, самое правильное, писать из разных потоков в одну очередь. А в отедльной задаче выгребать из очереди сообщения, и писать их в файл. Тут уже хоть в один, хоть в несколько, т.к. только один поток заведует логом.


--------------------
Выбор.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Mar 20 2018, 10:12
Сообщение #5


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Если подвести итог вышесказанному получиться что то такое
Код
FILE *g_log_fp;
int g_log_file_size;

void LOG_LogMessage(char *file, char *message, int value, int close)
{
    int file_size = 0;
    
    char buff[256] = { '\0' };
    char sval[10];
    
    ItoA(value, sval);
    strcat(buff, message);
    strcat(buff, sval);

    if (g_log_fp == NULL)
    {
        g_log_fp = fopen(file, "a+");
        
        if (g_log_fp != NULL)
            fputs(buff, g_log_fp);
    }
    else
        fputs(buff, g_log_fp);
    
    fseek(g_log_fp, 0, SEEK_SET);
    fseek(g_log_fp, 0, SEEK_END);
    file_size = ftell(g_log_fp);
            
    if (close)
        fclose(g_log_fp);
    else
        fflush(g_log_fp);
    
    if (file_size >= MAX_LOG_FILE_SIZE)
    {
        //LOG_Clear() ???
        //go to the next file ???
    }    
}

или я что то упустил в логике?

или через очередь ?
Код
char log_buffer[1024];
MSG_Q_ID log_messages_Q;

void LOG_Init(void)
{
    log_messages_Q = msgQCreate(100, 1024, 0);
}

void LOG_SengQ(char *message, int value)
{
    int size = strlen(message) + 4; //4 - for value
    char sval[10];
    
    log_buffer[0] = '\0';
    
    ItoA(value, sval);
    strcat(log_buffer, message);
    strcat(log_buffer, sval);
    
    msgQSend(log_messages_Q, log_buffer, size, NO_WAIT, MSG_PRI_NORMAL);
}

и потом в отдельном потоке msgQReceive(log_messages_Q, log_buffer, 1024, NO_WAIT); ?

я не думаю что очередь дает какие то преимущества.

Сообщение отредактировал Jenya7 - Mar 20 2018, 10:29
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Mar 20 2018, 10:40
Сообщение #6


Ally
******

Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050



Цитата(Jenya7 @ Mar 20 2018, 11:02) *
Как вообще сделать покрасивше?

Я исследовал быстродействие FatFS.
Результаты
Как видно время открытия и закрытия не такое уж критичное.
Поэтому у меня задача лога всегда открывает и закрывает файл после каждой инспекции очереди сообщений. Задача лога имеет самый низкий приоритет.
Очередь сообщений циклическая, особое внимание требует разруливание ситуаций переполнения очереди, поскольку это частая ошибка когда код начинает случайно логить в цикле.
А вот операция получения объема свободного места очень затратная по времени.
Так же не рекомендую создавать много мелких файлов, это увеличит время открытия и закрытия файлов.
Надо также думать сколько открытых файлов может одновременно поддерживать файловая система и сколько это занимает памяти.
Лучше не держать долго открытые файлы. Тогда лог будет иметь меньше влияния на остальной код который тоже может применять FS.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Mar 20 2018, 10:50
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(AlexandrY @ Mar 20 2018, 15:40) *
Я исследовал быстродействие FatFS.
Результаты
Как видно время открытия и закрытия не такое уж критичное.
Поэтому у меня задача лога всегда открывает и закрывает файл после каждой инспекции очереди сообщений. Задача лога имеет самый низкий приоритет.
Очередь сообщений циклическая, особое внимание требует разруливание ситуаций переполнения очереди, поскольку это частая ошибка когда код начинает случайно логить в цикле.
А вот операция получения объема свободного места очень затратная по времени.
Так же не рекомендую создавать много мелких файлов, это увеличит время открытия и закрытия файлов.
Надо также думать сколько открытых файлов может одновременно поддерживать файловая система и сколько это занимает памяти.
Лучше не держать долго открытые файлы. Тогда лог будет иметь меньше влияния на остальной код который тоже может применять FS.

так все таки с очередями лучше чем первый вариант? я не вижу существенной разницы. только в первый вариант нужно добавить семафор.

Сообщение отредактировал Jenya7 - Mar 20 2018, 10:50
Go to the top of the page
 
+Quote Post
andrew_b
сообщение Mar 20 2018, 11:25
Сообщение #8


Профессионал
*****

Группа: Свой
Сообщений: 1 975
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(Jenya7 @ Mar 20 2018, 13:12) *
Код
    char buff[256] = { '\0' };
     strcat(buff, message);
     strcat(buff, sval);


Что, 255 байт хватит всем?
Никогда не используйте функции, не контролирующие выход за границу буфера. Используйте strncat, уж если на то пошло. Или strlcat.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 20 2018, 12:00
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Jenya7 @ Mar 20 2018, 12:50) *
так все таки с очередями лучше чем первый вариант? я не вижу существенной разницы. только в первый вариант нужно добавить семафор.

Если у вас суперцикл - разницы нет.
Если многозадачная ОС - без понимания работы в многопоточном окружении можете писать только шлак.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Mar 20 2018, 12:01
Сообщение #10


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(andrew_b @ Mar 20 2018, 16:25) *
Что, 255 байт хватит всем?
Никогда не используйте функции, не контролирующие выход за границу буфера. Используйте strncat, уж если на то пошло. Или strlcat.

IAR давал мне возможность
Код
int size = strlen(message);
char buff[size ] = { '\0' };

в vxWorks я такую возможность не нашел вот и извращаюсь. динамическую алокацию отвергаю по возможности.

Сообщение отредактировал Jenya7 - Mar 20 2018, 12:11
Go to the top of the page
 
+Quote Post
k155la3
сообщение Mar 20 2018, 12:13
Сообщение #11


Профессионал
*****

Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848



Цитата(Jenya7 @ Mar 20 2018, 12:02) *
У меня по всему коду разбросанны сообщения типа
printf ("LIB ID = %d\n", lib_id);
. . .
Сейчас нужно некоторые сообщения логировать в файл на SD карте.
. . .
Как вообще сделать покрасивше?

Rem:
ф-ия printf довольно "массивная" из-за своей универсальности. Соотв-но время на ее работу немалое.
Вам возможно имеет смысл пересмотреть структуру вывода на терминал и логгирования
с точки зрения "событийности".
При возникновении события вместо "балета" с формированием строки через printf и выводом ее на USART
фиксировать данные по этому событию в бинарной форме { Timestamp, CodeEventId , DataEvent }.
При этом все пишется в очередь, из которой эти записи извлекаются и выводятся в лог (без переформатирования)
и на терминал (через парсер-конвертер с printf)

Неэффективно использовать в лог-массивах данные в не оптимальном "человеческом" формате.
Их неудобно обрабатывать, они занимают больше места.


Go to the top of the page
 
+Quote Post
andrew_b
сообщение Mar 20 2018, 12:13
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 1 975
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Цитата(Jenya7 @ Mar 20 2018, 15:01) *
IAR давла мне возможность
Код
int size = strlen(message);
char buff[size ] = { '\0' };

в vxWorks я такую возможность не нашел
Это C99 как минимум.
Цитата
вот и извращаюсь. динамическую алокацию отвергаю по возможности.

Вы не поняли.
Если вы выделили под сообщение буфер определённого размера, то strncat не позволит выйти за границу буфера. Она просто обрежет сообщение по длине.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Mar 20 2018, 12:14
Сообщение #13


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(jcxz @ Mar 20 2018, 17:00) *
Если у вас суперцикл - разницы нет.
Если многозадачная ОС - без понимания работы в многопоточном окружении можете писать только шлак.

у меня ОС с задачами. выделить одну задачу на забор пакетов из очереди и записи в файл? я SD не задушу потоком сообщений?
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 20 2018, 12:21
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(andrew_b @ Mar 20 2018, 14:13) *
Если вы выделили под сообщение буфер определённого размера, то strncat не позволит выйти за границу буфера. Она просто обрежет сообщение по длине.

IAR имеет более эффективные средства печати в буфер (в памяти) ограниченного размера, чем собирать его strncat() или чем то ещё.
Т.е. - естественно не сам IAR, а stdlib которую он использует.
Go to the top of the page
 
+Quote Post
Jenya7
сообщение Mar 20 2018, 12:24
Сообщение #15


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(jcxz @ Mar 20 2018, 17:21) *
IAR имеет более эффективные средства печати в буфер (в памяти) ограниченного размера, чем собирать его strncat() или чем то ещё.
Т.е. - естественно не сам IAR, а stdlib которую он использует.

какие? только не говорите sprintf sm.gif
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 6th July 2025 - 13:53
Рейтинг@Mail.ru


Страница сгенерированна за 0.01778 секунд с 7
ELECTRONIX ©2004-2016