Перейти к содержанию
    

Структуры данных

Подскажите мне вот такую вещь

я хочу реализовать какой то хранитель или тип для данных разного размера

пример: по COM порту приходит пачка данных размером от

10 до 1000 байт.

я хочу положить их в свою структуру данных

данные разного размера

в какой то другом потоке я их забираю по указателю

если это что то типа связного списка или очередеи

то я вижу что там данные одного размера

чета я не понимаю, как мне сделать

чтобы хранить разный размер.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Примерно так:

typedef union    //rx_tx_packet_union
  {
    unsigned char buffer[SIZE_RX_TX_BUFFER];
      
/// принимаемые короткие
    short_rx_input        sh_rx;        // короткая посылка приема
    tag_packet_check_struct         tag_check;
    tag_packet_prog_struct             tag_prog;            // 
    tag_packet_password_struct        tag_password;
    
/// принимаемые длинные
    long_rx_input        lg_rx;        // длинная  посылка приема
      
/// передаваемые короткие
    short_tx_output        sh_tx;        // короткая посылка передачи
    master_packet_struct             master_send;            //

/// передаваемые длинные
//    long_tx_output        lg_tx;        // длинная  посылка передачи
  }rx_tx_packet_union;

 

Ну и пример парочки структур:

typedef struct    // short_rx_input
  {
    unsigned char     data[2][3];        // 
    unsigned char     parity[2][3];    // 
  }short_rx_input;

typedef struct    //tag_packet_check_struct
  {
    unsigned long     rnd            :8;        // 
    unsigned long      low_bat        :1;        // 
    unsigned long      button        :1;        // 
    unsigned long     cnt            :22;    // 
    unsigned int     signature;            // 
   }tag_packet_check_struct;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не очень понял вопрос.

Нужно как то хранить посылки разной длины?

Список списков подойдет?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

я хочу реализовать какой то хранитель или тип для данных разного размера

пример: по COM порту приходит пачка данных размером от

10 до 1000 байт.

я хочу положить их в свою структуру данных

данные разного размера

Если вы хотите статический буфер, то придется выделять память под максимальный размер данных.

Далее применять union, как расписал ArtemKAD

 

Если же вы хотите каждый раз иметь буфер различной длины по размеру пришедшего пакета,

то применяйте динамическое выделение памяти из heap, при помоши malloc/free.

В первом слове буфера храните длину данных,

указатель на буфер передавайте в другой поток для чтения. Семафоры не забудьте.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если вы хотите статический буфер, то придется выделять память под максимальный размер данных.

Далее применять union, как расписал ArtemKAD

 

Если же вы хотите каждый раз иметь буфер различной длины по размеру пришедшего пакета,

то применяйте динамическое выделение памяти из heap, при помоши malloc/free.

В первом слове буфера храните длину данных,

указатель на буфер передавайте в другой поток для чтения. Семафоры не забудьте.

 

похоже придется сделать кольцевой буфер на максимальное число

с malloc/free мне не нравится-так как засегментируется все за час

при интенсивном использовании

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

кольцевой буфер на максимальное число

Зачем кольцевой? Почему не линейный?

Приняли посылку разной длины - разобрали, начиная с начала (сохраняя поля в структуру), поставили указатель на начало, начали опять принимать.

Если нужно принимать во время разбора - можно принимать в другой буфер, все равно в обоих случаях размер памяти не меняется.

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

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Зачем кольцевой? Почему не линейный?

Приняли посылку разной длины - разобрали,

Пока разбираешь, пару-тройку байт из потока теряешь. Что-бы не терять за время разбора кольцевой буфер и нужен.

можно принимать в другой буфер, все равно в обоих случаях размер памяти не меняется.

Меняется. Кольцевой буфер обычно гораздо меньше основного.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тут уже упоминали, что для передачи данных правильно применять сериализацию данных вместо простого копирования принятых байтов в union?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тут уже упоминали, что для передачи данных правильно применять сериализацию данных вместо простого копирования принятых байтов в union?

Например? Особенно по части приема...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну имеется ввиду, что существуют разные архитектуры процессоров. С разными требованиями по выравниванию данных. И даже с разным расположением байт в многобайтовых интах.

Таким образом описанная абсолютно одинаково на языке Си структура будет представлена в памяти совершенно по-разному!

Если обе системы и для приёма и для передачи будут применять простое копирование этого региона памяти в линию передачи данных то при неудачном стечении обстоятельств вы прините совсем не то что вам отправляли.

 

Например STM8 big endian - вообще редкость, скажем так.

На AVR требований по выравниванию нет и все поля структуры лягут в память по порядку без дыр.

На STM32 же между uint8 и uint32 в структуре будет padding т.е. дыра.

 

Всё это не важно пока и приёмник и передатчик работают на одном процессоре(точнее с одинаковым порядком байт и требованиями по выравниванию).

 

Кажется в этой статье можно найти что-то полезное на эту тему.

https://thatskriptkid.wordpress.com/2015/01...80%D1%83%D0%BA/

 

И вот что-то нашел

https://habrahabr.ru/company/xakep/blog/258959/

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну имеется ввиду, что существуют разные архитектуры процессоров. С разными требованиями по выравниванию данных. И даже с разным расположением байт в многобайтовых интах.

Таким образом описанная абсолютно одинаково на языке Си структура будет представлена в памяти совершенно по-разному!

Если обе системы и для приёма и для передачи будут применять простое копирование этого региона памяти в линию передачи данных то при неудачном стечении обстоятельств вы прините совсем не то что вам отправляли.

 

Например STM8 big endian - вообще редкость, скажем так.

На AVR требований по выравниванию нет и все поля структуры лягут в память по порядку без дыр.

На STM32 же между uint8 и uint32 в структуре будет padding т.е. дыра.

#pragma pack(1)

 

или __packed для описания структуры

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

 

И вот что-то нашел

https://habrahabr.ru/company/xakep/blog/258959/

По-моему в этом "что-то" как раз написано почему сериализацию лучше не делать.

 

По-моему весьма однозначно:

WARNING

 

Если дорожишь эффективностью при передаче данных, то отдавай предпочтение бинарным протоколам (если, конечно, у тебя есть выбор).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

#pragma pack(1) вроде как моветон, на сколько я знаю.

 

Я приведенные ссылки полностью не читал, но в моем понимании бинарность протокола не исключает нормальной сериализации структур и приведения протокола к стандартному порядку байт... Передавать всё в JSON я не предлагал на маленьком контроллере )

 

In computer science, in the context of data storage, serialization is the process of translating data structures or object state into a format that can be stored (for example, in a file or memory buffer) or transmitted (for example, across a network connection link) and reconstructed later (possibly in a different computer environment).[1] When the resulting series of bits is reread according to the serialization format, it can be used to create a semantically identical clone of the original object.

 

В предложенном выше в топике подходе, для сериализации тупо используется memcpy из структуры в буфер->линия передачи данных->буфер->memcpy в union. Со всеми вытекающими последствиями о которых я говорил ранее.

 

По идее вы должны вместо memcpy() реализовать некий метод serialize() который структуру преобразует в поток байтов в соответствии с принятым стандартом(serialization format). На приёмнике обратное преобразование. И никто не запрещает сделать этот протокол бинарным. Передача чего-то вроде JSON или строк - всего лишь частный случай serialization format.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

#pragma pack(1) вроде как моветон, на сколько я знаю.

 

Передавать набор упакованных структур (и принимать такой же набор) - вполне себе рабочий метод организации обмена. Просто, быстро и читается довольно легко.

Вот дальше работать с этими структурами - моветон, да (хотя, если дороже перекладывать туда-сюда - почему бы и нет?).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

#pragma pack(1) вроде как моветон, на сколько я знаю.

Плохо знаешь. Моветон использовать его для рабочих переменных из-за оверхеда в коде при работе на 32 разрядных платформах. А там где надо что-бы было как написано, а не как оптимизатор посчитал нужным, там ему самое место.

 

 

Я приведенные ссылки полностью не читал, но в моем понимании бинарность протокола не исключает нормальной сериализации структур и приведения протокола к стандартному порядку байт... Передавать всё в JSON я не предлагал на маленьком контроллере )

Ну если не JSON, то ваять придется нечто свое. А значит вставлять дополнительные поля в передаваемые данные с метаинформацией и разбирать метаинформацию на приемном конце и все это писать своими руками. И что это поменяет кроме оверхеда в передаваемых данных, оверхеда в коде и оверхеда во времени обработки? Теперь надо особо обрабатывать не только на отдельных платформах, а обрабатывать метаинформацию в рантайме на всех платформах.

 

 

 

По идее вы должны вместо memcpy() реализовать некий метод serialize() который структуру преобразует в поток байтов в соответствии с принятым стандартом(serialization format). На приёмнике обратное преобразование. И никто не запрещает сделать этот протокол бинарным. Передача чего-то вроде JSON или строк - всего лишь частный случай serialization format.

 

По-моему, у топикстартера как раз работа и состоит в том, что приходит некий поток данных который надо разобрать. Т.е. вашим языком - у него вопрос по реализации самой "deserialize()"

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...