Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Блокировка чтения из файла

4.9K
13 апреля 2007 года
efferson
57 / / 08.12.2005
Суть проблемы такова - есть бесконечный цикл, который должен считывать данные из файла по мере их дозаписи в файл. Правильно ли я понимаю, что при открытии файла без указания флага O_NONBLOCK по достижению конца файла ф-ция read() будет ждать поступления в него новых данных? Если же нет, то как на ваш взгляд сию проблему можно решить иначе окромя как очередями IPC?
2.4K
13 апреля 2007 года
Lexogen
70 / / 18.05.2004
Если у Вас возник вопрос о межпроцессном взаимодействии - используйте механизмы для этого предназначенные: именнованные каналы, сокеты или shared memory. Они достаточно хорошо описанны в литературе. В зависимости от задачи выбирайте наиболее подходящий Вам и не изобретайте велосипед.
4.9K
14 апреля 2007 года
efferson
57 / / 08.12.2005
В том то и проблема, что стандартные средства ipc по ряду причин мне не подойдут.
361
14 апреля 2007 года
Odissey_
661 / / 19.09.2006
Цитата:
В том то и проблема, что стандартные средства ipc по ряду причин мне не подойдут.


Поделитесь почему, возможно решение проблемы лежит на этапе проектирования ? =)

Цитата:
Правильно ли я понимаю, что при открытии файла без указания флага O_NONBLOCK по достижению конца файла ф-ция read() будет ждать поступления в него новых данных?


Нет, ждать не будет =), вы же O_NONBLOCK поставили. Вернет управление вашему процессу, возвратом функции по идее будет -1, а errno установится в EAGAIN. Обычно так читаются FIFO файлы или файлы устройств.

Цитата:
как на ваш взгляд сию проблему можно решить иначе окромя как очередями IPC?


Хм. Почему только очереди IPC? Кроме очередей, можете использовать разделяемую память IPC.
Если уж IPC ну ни как вас не устраивает, используйте локальные сокеты или FIFO файлы.

Офф.
У меня такое ощущение что вы каждый раз выдумываете велосипед =), без обиды, правда... в теме "Вызов внешних программ" вы городили тучу вызовов fork и exec, а на предложенный popen даже не взглянули. О нем часто забывают, но ваша проблема бы решалась в несколько строчек кода =). Порой проблема решается проще если рассмотреть вопрос с другого ракурса.

4.9K
16 апреля 2007 года
efferson
57 / / 08.12.2005
Возможно Вы и правы... Как бы вы поступили на моём месте - есть сервер чата, порождающий пул потомков. Требуется, что бы по приходу сообщения от клиента одному из потомков, оно отсылалось сервером всем клиентам. Т.е. организовать чат :)
Сейчас у меня это сделано следующим образом - создается файл, открывается писательный дескриптор ( используется всеми потомками для записи вновь пришедшего сообщения). В каждом потомке создаётся читательный дескриптор, после чего в бесконечном цикле aka
while( ( nRead = read( fd, &data, SIZE_DATA ) ) >= 0 ) из файла вынимаются вновь пришедшие данные.... Проблема только в том, что при достижении конца файла вызов не блокируется, а начинает считывать данные размером 0. Вот и приходиться каждый раз просматривать, что я там считал... :)

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

На Ваш взгляд последняя идея имеет право на существование? И вобще как бы Вы решили эту задачу?
361
16 апреля 2007 года
Odissey_
661 / / 19.09.2006
Думаю имеет.
Я бы делал так. При подключении нового клиента создавал бы отдельный файл для него (или область памяти) и в него бы писался текущий "слепок" разговора всеми потоками пула через семафор. Через заданный промежуток "слепок" отправлялся бы клиенту. Так проще с группами и приватом, да и вообще :) ИМХО, но трафик больше.
2.4K
17 апреля 2007 года
Lexogen
70 / / 18.05.2004
Цитата: efferson

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

На Ваш взгляд последняя идея имеет право на существование? И вобще как бы Вы решили эту задачу?



Имеет право. И на данный момент для такой схемы придуман паттерн producer/consumer. Примеры его реализации как с семафорами так и с условными переменными есть в нете. Но обычно для реализации используются два семафора.

Вот пример для солярки:

Код:
typedef struct {
 char buf[BSIZE];   // if empty==BSIZE buffer is empty. if empty==0, then it's full
 sema_t occupied, empty;
 int nextin, nextout;
 sema_t pmutex, cmutex;
} BUFFER;

initialization section
BUFFER *bufferp; // allocate a pointer to a BUFFER
bufferp = malloc( sizeof(BUFFER) );                                // create a BUFFER type
sema_init(&buffer->occupied, 0, USYNC_THREAD, 0);     // force consumer to always wait first
sema_init(&buffer->empty, BSIZE, USYNC_THREAD, 0); // allow for BSIZE accesses, i.e, buf is empty
sema_init(&buffer->pmutex, 1, USYNC_THREAD, 0);       // producer mutex
sema_init(&buffer->cmutex, 1, USYNC_THREAD, 0);       // consumer mutex
bufferp->nextin = 0; // initialize ring buffer
cond_init( &count_nonzero, USYNC_THREAD, 0);          // intraprocesss usage

 
void producer (BUFFER *b, chare item) {
 sema_wait( &b->empty );
 sema_wait( &b->pmutex );                          // protect against other   producers accessing this buffer
 b->buf[ b->nextin ] = item;                           // insert datum
 b->nextin = (b->nextin + 1 ) % BSIZE;         // ring buffer
 sema_post( &b->pmutex );                         // allow other producers in
 sema_post( &b->occupied );                      // let any consumers know a  datum is available
}
 
char consumer(BUFFER *b) {
 char item;
 sema_wait( &b->occupied );                   // wait if another consumer or  producer is here
 sema_wait( &b->cmutex );                       // protect buffer against other  consumers
 item = b->buf[ b->nectout ];                     // get next datum from buffer
 b->nextout = (b->nextout + 1) BSIZE;       // ring buffer
 sema_post( &b->cmutex );                       // allow other consumers into  this buffer
 sema_post( &b->empty );                        // let producer know of buffer's  status
 return ( item );
}


Код не мой, и к сожалению не могу вспомнить откуда брал.

Если чат в локалке, то для общих сообщений можна и broadcast использовать...
502
22 апреля 2007 года
Jail
550 / / 30.01.2007
IPC вполне подходящий вариант и решит все твои задачи. efferson, ты опять просто тратишь время на изобретение даже не вилосипеда, а колеса)))))
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог