вторник, 29 ноября 2011 г.

Работа с данными при инкапсуляции/декапсуляции сообщения

При формировании или интерпретации пакета в рамках определённого протокола есть 2 способа работы с данными (под данными я буду подразумевать полезную нагрузку по отношению к текущей степени вложенности):
  • создание отдельного буфера данных для данного протокола;
  • на всём пути обработки кадра пользоваться памятью, выделенной для самого низкоуровнего протокола.
Первый путь наиболее прост и минимизирует вероятность ошибок, особенно, при плохо налаженном механизме блокировок при асинхронном характере поступающих данных. Но есть пару минусов: увеличение времени на обработку пакета, связанную с копированием одних и тех же данных из одного буфера в другой и увеличение требований к ОЗУ, которая используется для этих буферов.

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


Структура raw_msg характеризует более низкоуровненый протокол, а high_msg - высокоуровневый. Для простоты предположим, что у каждого протокола есть только по одному служебному полю - поле адреса.

struct raw_msg {
    RAW_ADDR addr;
    unsigned char *data;
    int length;
}

struct high_msg {
    HIGH_ADDR addr;
    unsigned char *data;
    int length;
}

Тогда, для первого случая:
void high_input(struct raw_msg *rmsg) {
    struct high_msg hmsg;
    unsigned char high_data[MAX_HIGH_DATA_SIZE];
    int i;

    hmsg.data = high_data;

    hmsg.addr = rmsg->data[ADDR_OFF];

    for(i = 0; i < rmsg->length; i++)
        hmsg.data[i] = rmsg->data[i + RAW_DATA_OVERHEAD];

    hmsg.length = rmsg->length - RAW_DATA_OVERHEAD;

    /* Дальнейшая обработка hmsg */
}

void high_output(RAW_ADDR raddr, struct high_msg *hmsg){
    struct raw_msg rmsg;
    unsigned char raw_data[MAX_RAW_DATA_SIZE];
    int i;

    rmsg.data = raw_data;

    rmsg.addr = raddr;
    rmsg.data[ADDR_OFF] = hmsg->addr;

    for(i = 0; i < hmsg->length; i++)
        rmsg.data[i + HIGH_DATA_OVERHEAD] = hmsg->data[i];

    rmsg.length = hmsg->length + RAW_DATA_OVERHEAD;

    /* Передача rmsg */
}


Альтернативно можно выделить 2 буфера (I/O), размер которых равен максимальному размеру самого низкоуровнего пакета в системе (опишу случай только для входящего сообщения).

unsigned char in_raw_data[MAX_RAW_DATA_SIZE];
unsigned char out_raw_data[MAX_RAW_DATA_SIZE];

void high_input(struct raw_msg *rmsg) {
    struct high_msg hmsg;
    unsigned char *high_data;

    hmsg.addr = rmsg->data[ADDR_OFF];

    /* Ничего никуда копировать не нужно. rmsg->data ссылается на in_raw_data */
    hmsg.data = rmsg->data + RAW_DATA_OVERHEAD;

    hmsg.length = rmsg->length - RAW_DATA_OVERHEAD;

    /* Дальнейшая обработка hmsg */
}


Комментариев нет:

Отправить комментарий