LINUX.ORG.RU

Задачка


0

0

Привет!

Есть задачка.
Имеется процесс, производящий чтение из некоторого абстрактного 
буфера (это может быть например буфер приёма UDP и т.п.)
За один раз из буфера процесс читает один пакет данных.
Скорость записи в буфер может быть очень большой и если процесс 
не будет успевать читать пакеты, то они будут пропадать безвозвратно.
Соответственно идеальной будет следующая схема работы:
...
...
while(1)
  {
    pkt = ReadPktFromBuf();
    WritePktToQueue(pkt);
  }
...
...

Здесь только что прочитанный пакет сразу же (_без_ всякой обработки)
пришется в некоторую очередь.
Т.о. риск потери пакетов сведён к минимуму.

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

Вопрос:
Какими средствами IPC можно эмулировать данную абстрактную очередь
так, чтобы время записи в неё было минимальным?
При этом у другого процесса должна быть возможность читать из начала
очереди.

Я буферю обычно так: Создаёшь в shared mem циклический буфер - (размер пакета)*N, где N - max длина очереди. Один процесс будет скидывать пакеты, другой читать. Засинхронизировать можешь тоже через shared mem регистры. Будет быстро.

eraser
()

Канал?

из `man 7 pipe`:

If a process attempts to read from an empty pipe, then read(2) will block until data is available. If a process attempts to write to a full pipe (see below), then write(2) blocks until sufficient data has been read from the pipe to allow the write to complete. Non-blocking I/O is possible by using the fcntl(2) F_SETFL operation to enable the O_NONBLOCK open file status flag.

ale ★★
()
Ответ на: комментарий от eraser

>Размер FIFO щграничен. Можно потерять данные...

я имел ввиду pipe, а по поводу потери данных - читайте выше

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

> я имел ввиду pipe

pipe работает по принципу FIFO...

> а по поводу потери данных - читайте выше

И что ? Если процесс читатель задержался, FIFO заполнено, а новый пакет пришёл - потеря... И размер у pipe ограничен, по-моему 512Б.

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

>И что ?

Ну уж коли вы не удосужились перевести - бегло переведу сам

Если процесс хочет прочитать из "пустого" канала, то вызов read БЛОКИРУЕТСЯ до момента появления новой информации

Если процесс собирается писать в "заполненный" канал, то write БЛОКИРУЕТСЯ пока не будет прочитана информация из этого канала

>Если процесс читатель задержался, FIFO заполнено, а новый пакет пришёл - потеря... И размер у pipe ограничен, по-моему 512Б.

не доверяете моему беглому переводу - удосужтесь прочитать `man 7 pipe`

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

> а иначе как работает ` cat <большой файл> | less `

Вот в этом и ошибка... <большой файл> - это статические данные, которые никуда не убегут. А если работаешь с внешним устройством (сетевуха, например), то оно ждать не будет. Если писатель блокирован по полному pipe'у, а пришёл новый пакет... всё... блокируй не блокируй... всёравно получишь - ....

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

>А если работаешь с внешним устройством (сетевуха, например)

>Вот в этом и ошибка...

вот-вот. Прошу не путать socket и pipe. pipe - исключительно локальная вещь (в том смысле, что оба дескриптора возвращаемых через filedes имеют смысл лишь в пределах одной ОС) и заблокировать вызов write не составляет труда.

Если вы не согласны с моим высказыванием - попрошу пример простейшей программы, где pipe берет данные "с внешних устройств" с сетевухи например =)

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

>Если вы не согласны с моим высказыванием - попрошу пример простейшей программы, где pipe берет данные "с внешних устройств" с сетевухи например =)

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

Может стоит пользовать очереди из System V IPC?

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

>(указанного в условии задаче)

самый первый пост:

>абстрактного буфера (это может быть например буфер приёма UDP и т.п.)

первый мой пост, содержал вопрос "Канал?". Посему я не навязываю свою точку зрения.

Каналы не подходят для решения с учетом приема UDP пакетов (кстати, если нужна передача данных без потерь - все же лучше TCP), ибо каналы - локальная вещь, а не по причинам, произнесенным eraser (про то, что shared memory быстрее - я знаю)

Относительно постановки задачи, это не одно и тоже:

>что блокировака при постановке в очередь недопустима

>чтобы время записи в неё было минимальным?

зы единственное, что я додумал в постановке задачи - гарантированный прием сообщений =)

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

> Имеется процесс, производящий чтение из некоторого абстрактного 
буфера (это может быть например буфер приёма UDP и т.п.)
За один раз из буфера процесс читает один пакет данных.....

Так как чел не определился, что ему надо, может не знает.... Предлагаю наиболее универсальное решение - буфер в shared mem. Это наибольшая скорость и минимальный риск в потери данных. Pipe - хорошо... синхронизацию обеспечивает замечательно... но ...
>>зы единственное, что я додумал в постановке задачи - гарантированный прием сообщений =)

Гарантированный нриём уж точно не обеспесит ...

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

>Гарантированный нриём уж точно не обеспесит ...

я извиняюсь, вы - дурак, или притворяетесь? я вам дал выдержку из мана, бегло перевел его, попросил привести аргументы опровержения моих слов или рабочий пример, а вы заладили как попугай - мол потеряются данные и все... ФАКТЫ давайте оперировать фактами. Что привели вы в доказательство своих слов?

ale ★★
()
Ответ на: комментарий от eraser

>Моск включи... Перевотчик хренов... И почитай внимательно, что я писал... Тогда может и асилишь...

> Гарантированный нриём уж точно не обеспесит ...

сия фраза может относиться лишь к каналам, если нет - выражайтесь яснее.

Что это, как не гарантированный прием?

If a process attempts to write to a full pipe (see below), then write(2) blocks until sufficient data has been read from the pipe to allow the write to complete

Вы не сможете записать информацию в заполненный канал, пока не будут прочитаны данные с этого pipe'а - куда "уйдет" информация? или же вы думаете процесс по "какомуто наитию" саморазблокируется и начнет писать?

ps вобщем, при отсутствии аргументов с вашей стороны, бесполезную дискуссию прекращаю.

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

Ты никак не хочешь понять, что процесс, который пишет в pipe, данные берёт из внешнего устройства (так вопрос звучал, например сетевуха, плата сбора данных и т.д.), которому положить на обмен между процессами. Допустим, процесс1 - берет данные из внешнего устройства (пакет данных) с некоторым тактом и пишет в pipe, а процесс2 - читает их и обрабатывает. Так вот процесс1 должен успеть прочитать данные из устройства и передать их в процесс2. Может возникнуть ситуация, когда процесс1 блокирован по записи в полный pipe, а устройство хочет передать данные процессу2. Т.К. устр-во вечно ждать не может, если процесс1 не успеет разблокироваться - пакет пропадёт. Пойми! Данные могут пропасть не в сечении процесс1 -> процесс2, а в сечении устройство -> процесс1 !!!!! Ну уж как более понятно тебе объяснит я не знаю....

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

>Данные могут пропасть не в сечении процесс1 -> процесс2, а в сечении устройство -> процесс1 !!!!!

вот, а каким образом происходит коммутация "устройство->процесс1" и "процесс1->процесс2"? Применение каналов, я рассматриваю только ко второму случаю ("процесс1->процесс2"), и здесь при наличии информации у процесса1 она гарантированно будет передана процессу2.

>если процесс1 не успеет разблокироваться - пакет пропадёт

это уже вопрос реализации процесса1 и вопросу коммутации "устройство->процесс1".

Теоретически, даже с разделяемой памятью может возникнуть ситуация, описанная выше, но из-за скорости передачи "процесс1->процесс2" вероятность возникновения данной ситуации ("не успеет разблокироваться - пакет пропадёт") меньше, чем при применении каналов. Но при этом вероятность - все же есть, и её исключать нельзя.

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

> и здесь при наличии информации у процесса1 она гарантированно будет передана процессу2.

Да, но организация процесс1->процесс2 напрямую влияет на взаимодействие устройство->процесс1. 

> Теоретически, даже с разделяемой памятью может возникнуть ситуация, описанная выше

Может, но это надо учитывать при проектировании системы. Нужно чтоб 
Td > Tr + Tw, где
Td - min период выдачи данных устройством;
Tr - время чтения данных процессом1;
Tw - время передачи процесс1->процесс2.

Td может быть таким, что полюбому будут потери, тогда....
А может бать таким, что с shared будет всё ОК, а с pipe'ом - нет, но не наоборот! Так, что пусть товарисч решает, что ему нужно.

eraser
()

Может, я невнимательно читал. Не вижу в условии ничего, что объясняло бы в вопросе упоминания IPC. Если конечно, под IPC понимается межпроцессное взаимодействие. Для решения задачи, как я её понял, достаточно потоков + std::queue (или аналога). push и pop, естественно д.б. синхронизированны.

gpg
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.