Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Не могу разобраться с FIFO при работе с потоками, Не могу разобраться с FIFO при работе с  
:(
    Опции темы
wvlg
Дата 6.6.2008, 20:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 2.6.2008

Репутация: нет
Всего: нет



 Изначально задача стоит так:
Происходит работа с драйвером сетевых устройств. Ставиться фильтр на перехват пакетов (например, по IP и порту назначения удаленного хоста, т.е фильтруются исходящие на него и приходящие с него пакеты). 
 Далее, необходимо определить когда пользователь начал работу с удаленным хостом (началом работы считается первый перехваченный пакет К хосту). После такого пакета необходимо: 
1. "запомнить" порт(локальный) с которого он отправлен.
2. Создать поток,  которому в дальнейшем будут передаваться на обработку все пакеты, отосланные с этого локального порта (и все пакеты, корые ему будут адресованы). Этот поток будет их обрабатывать (неважно как, просто производить действия, например, заменять полученные\отосланные байты данных)
3. После обработки пакета его необходимо отправить получателю. (Или проигнорировать)
4. Вопрос встал в том КАК эти самые пакеты передавать потокам-обработчикам. А потом обратно главному потоку, чтобы он непосредственно их отправил.

 Дело в том, что пользователь может открыть несколько сессий работы с сервером. (Т.е. отправлять\получать с\на разных локальных портов пакеты на\с удаленный хост). Каждая такая "сессия"  должна обрабатываться отдельным потоком программы. (как я себе представляю).
 Далее полагаю, что задача основного потока. Определить ПортПользователя. Создать поток для его обработки, если такового еще нет. Передать пакет на обработку. Я предположил ввести контейнер FIFO для работы с каждым таким потоком. Т.е. пришел пакет такого-то ПортаПользователя-его "пихаем" в такой-то контейнер. А далее поток "сам с ним работает".
Встал вопрос. Не может ли возникнуть конфликта при одновременном обращении к такому контейнеру? Т.е. может возникнуть момент, когда в таком контейнере "накопиться" определенное число пакетов и к нему (контейнеру) могут одновременно обратиться основной поток (чтобы положить туда очередной пакет) и поток обрабатывающий пакеты, лежащие там. Будет ли конфликт при таком одновременном обращении? (вопрос кажется странным, т.к. в любой  момент времени два потока все же не работают одновременно(с такими контейнерами), по идее не должно быть проблем, но все же...)

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

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


Это сообщение отредактировал(а) wvlg - 6.6.2008, 23:36
PM MAIL   Вверх
wvlg
Дата 7.6.2008, 10:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 2.6.2008

Репутация: нет
Всего: нет



 Задам немного другой вопрос. Также относящийся сюда.
Каким образом организовать контейнер в который можно записывать одним потоком когда угодно, а вторым из него же брать когда угодно?
 Такой контейнер, чтобы не было конфликтов одновременного доступа и, самое главное не было ЗАДЕРЖКИ на запись в такой контейнер (хотя бы именно на запись). Т.е. поток, записывающий данные в контейнер, не должен "думать" занят тот или нет. Как такое реализовать?

Контейнер типа FIFO.

Это сообщение отредактировал(а) wvlg - 7.6.2008, 10:51
PM MAIL   Вверх
sparn
Дата 11.6.2008, 14:06 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 21
Регистрация: 11.5.2006

Репутация: нет
Всего: 1



Цитата

Встал вопрос. Не может ли возникнуть конфликта при одновременном обращении к такому контейнеру? Т.е. может возникнуть момент, когда в таком контейнере "накопиться" определенное число пакетов и к нему (контейнеру) могут одновременно обратиться основной поток (чтобы положить туда очередной пакет) и поток обрабатывающий пакеты, лежащие там. Будет ли конфликт при таком одновременном обращении? (вопрос кажется странным, т.к. в любой  момент времени два потока все же не работают одновременно(с такими контейнерами), по идее не должно быть проблем, но все же...)


Конфликт будет если не использовать критические секции для защиты контейнера от одновременного доступа из разных потоков. Как может возникнуть конфликт: "клиентский" поток пытается добавить в конец очереди пакет, в этот момент обрабатывающий поток выбирает один или все первые пакеты, как результат, потери пакетов+утечки памяти или неверные смещения/указатели+исключительные ситуации. Из личного опыта и исходя из закона Мерфи если будет хоть малейшая лазейка для рассинхронизации, то эта гадость обязательно случится. Что касается "в любой  момент времени два потока все же не работают одновременно" - так было на одноядерных, однопроцессорных машинах, сегодня даже на домашних компьютерах в один и тот же момент могут работать несколько потоков(как следствие многоядерных процессоров).

Добавлено через 4 минуты и 41 секунду
Цитата

Каким образом организовать контейнер в который можно записывать одним потоком когда угодно, а вторым из него же брать когда угодно?
 Такой контейнер, чтобы не было конфликтов одновременного доступа и, самое главное не было ЗАДЕРЖКИ на запись в такой контейнер (хотя бы именно на запись). Т.е. поток, записывающий данные в контейнер, не должен "думать" занят тот или нет. Как такое реализовать?


Используя механизм критических секций(ищи в msdn описание CRITICAL_SECTION, EnterCriticalSection, LeaveCriticalSection, InitializeCriticalSection, DeleteCriticalSection). Абсолютно без задержек это реализовать невозможно(т.к. в случае если один поток зашел в критическую секцию второй должен ждать пока первый не выйдет из неё), но можно свести их к минимуму.

пример FIFO для передачи пакетов между потоками:

делаем нужные объявления:
Код

// packet data declaration
struct packetData_s
{
    char*            packet;        // packet buffer
    int                size;        // packet size    

    packetData_s*    next;        // next item in list
};

CRITICAL_SECTION    queue_cs;    // critical section to protect packets queue
    
// packets queue
packetData_s*        first;        // first element
packetData_s*        last;        // last element


не забываем инициализировать:
Код

InitializeCriticalSection (&queue_cs);
first = NULL;
last = NULL;


добавляем пакет в конец списка таким образом:
Код

int  PushPacket (char *packet, int size)
{
    // create new instance of packet data structure and fill it
    packetData_s* packet_data = new packetData_s();

    // TODO: copy packet if needed
    packet_data->packet = packet;
    packet_data->size = size;
    packet_data->next = NULL;

    // add data to queue
    EnterCriticalSection (&queue_cs);
    if (NULL != first)
    {
        // queue is empty
        first = packet_data;
        last = packet_data;
    } // if (queue is empty)
    else
    {
        // queue is not empty
        last->next = packet_data;
        last = packet_data;
    } // else (queue is empty)
    LeaveCriticalSection (&queue_cs);

    return 0;
};


выбираем первый пакет из очереди таким образом:

Код

int  PopPacket (char *&packet, int &size)
{
    packetData_s* packet_data = NULL;

    // add data to queue
    EnterCriticalSection (&queue_cs);
    if (NULL != first)
    {
        // queue is not empty
        packet_data = first;
        first = packet_data->next;
    } // if (queue is not empty)
    LeaveCriticalSection (&queue_cs);

    if (NULL == packet_data)
    {
        return -1;
    } // if (queue was empty)

    packet = packet_data->packet;
    size = packet_data->size;

    delete packet_data;

    return 0;
};


и по завершении работы не забываем очистить список и вызвать: 
Код

DeleteCriticalSection (&queue_cs);

PM MAIL   Вверх
sparn
Дата 11.6.2008, 14:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 21
Регистрация: 11.5.2006

Репутация: нет
Всего: 1



Цитата

 Дело в том, что пользователь может открыть несколько сессий работы с сервером. (Т.е. отправлять\получать с\на разных локальных портов пакеты на\с удаленный хост). Каждая такая "сессия"  должна обрабатываться отдельным потоком программы. (как я себе представляю).


Модель "коннект-поток" не очень удачная(или совсем неудачная), не зря ведь придумываются всякие асинхронные сокеты. Чем больше потоков тем медленнее происходит переключение между ними, тем больше процессорного времени теряется впустую, более того во всех ОС есть максимальное количество потоков. Количество обрабатывающих потоков должно ИМХО зависеть лишь от количества процессоров/ядер(т.е например: кол-во_обрабатывающих_потоков = кол-во_ядер * 2).

Цитата

 Дело в том, что пользователь может открыть несколько сессий работы с сервером. (Т.е. отправлять\получать с\на разных локальных портов пакеты на\с удаленный хост). Каждая такая "сессия"  должна обрабатываться отдельным потоком программы. (как я себе представляю).


Думаю тут уместно будет выделить для отправки пакетов отдельный поток.
PM MAIL   Вверх
wvlg
Дата 17.6.2008, 09:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 17
Регистрация: 2.6.2008

Репутация: нет
Всего: нет



2 sparn
Спасибо за ответы!!! Теперь хоть точно знаю, что при работе с очередью "будут проблемы" (хотя один знакомый утверждал, что одновременное обращение "исключается самой структурой FIFO контейнеров").

 Вот только не совсем понятным остается как же тогда обрабатывать каждый коннект...
Цитата(sparn @  11.6.2008,  14:35 Найти цитируемый пост)
Модель "коннект-поток" не очень удачная(или совсем неудачная), не зря ведь придумываются всякие асинхронные сокеты.
...ИМХО зависеть лишь от количества процессоров/ядер(т.е например: кол-во_обрабатывающих_потоков = кол-во_ядер * 2).


 Честно говоря с трудом представляю как один поток смог бы обрабатывать несколько коннектов. Т.е. работал бы с пакетами, адресованными\посланными на\с разные порты... Дело в том, что работа такого потока как раз и зависит от содержания пакетов... Могу сказать, что в пакетах приходит машинный код, который необходимо будет исполнить. Поэтому и были мысли о том, чтобы для каждого коннекта создавать отдельный поток...
 Думал я и об ограничении при такой реализации. Но что поделать? Хотя было бы здорово, если бы возможно было обрабатывать данные в ограниченном количестве потоков, т.е. для каждого коннекта не создавать новый.
 Думается, можно уйти к решению с конечным числом потоков, если ввести какой-нибудь объект-исполнитель машинного кода. Т.е. есть объект, передаем ему строку на исполнение и этот объект хранит этот код и всегда его выполняет при вызове.... Хотя, наверное, тут необходимо все более детально изложить общую задачу, чтобы уйти от огромного количества потоков.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0468 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.