2010-12-04 5 views
0

Я собираюсь реализовать программу, в которой один родительский процесс читает текстовый файл и передает данные, которые он считывает, в буфер общей памяти, который будет считываться некоторыми дочерними процессами. Вся эта работа будет опосредована семафорами. Предположим, что родитель собирается читать по одному символу за раз из файла, а буфер общей памяти - 5 слотов.Вопрос о проблеме производителя/потребителя

Сначала я думал только имея 2 семафоры:

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

readSemaphore, инициализированный 0, является семафором, который сообщает, разрешено ли чтению из буфера читателю.

Но теперь, когда я думаю об этом, это не помешает мне иметь двух пользователей, одновременно получающих доступ к общей памяти. Я должен это предотвратить. Поэтому я ввел третий семафор:

allowedToRead, который является либо 1, либо 0, что позволяет или блокирует доступ к дочерним процессам.

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

Ребенок:

while (something) { 
    wait(readSemaphore) 
    wait(allowedToRead) 
    <<read from shared memory>> 
    post(allowedToRead) 
    post(writeSemaphore) 
} 

Родитель:

while (something) { 
    wait(writeSemaphore) 
    <<writes to shared memory>> 
    post(allowedToRead) 
} 

ли мои рассуждения правильно?

Благодаря

+0

Вы можете найти Boost.Interprocess полезно, чтобы сэкономить вам тяжелую работу при работе с общей памятью. Существуют прямые потоковые поточные процессы, описанные здесь: http://www.boost.org/doc/libs/1_45_0/doc/html/interprocess/streams.html – 2010-12-04 18:33:01

+0

Это для школы, поэтому никакого повышения для меня нет. – 2010-12-04 18:59:59

ответ

1

Хачик является наполовину. Он может быть в порядке, но его описание не так ясно, как могло бы быть.

Во-первых, если у вас есть родительская проводка allowedToRead, вы, вероятно, имеете в виду для нее сообщение readSemaphore.

Во-вторых, ваш код позволяет родителям писать одновременно с чтением ребенка. Вы говорите, что у вас 5 слотов. Если родитель записывает в другой слот, чем ребенок читает, то это нормально, я полагаю, но как ребенок определяет, где читать? Использует ли он те же переменные, что и родитель, чтобы определить, где писать? Вероятно, вам нужна дополнительная защита. В конце концов, я предполагаю, что разные дети читают разные слоты, поэтому, если вам нужно предотвратить их прохождение по ногам одного носа, вам нужно будет сделать то же самое и для родителя.

В-третьих, я бы использовал мьютекс вместо семафора для allowedToRead.

В-четвертых, что определяет, какой ребенок читает, какие данные или он должен был быть первым, первым служил, как свиньи, в ведро с отстойником?

Если в общей памяти имеется 5 независимых слотов, то я бы склонен добавить переменную «следующее чтение» и «следующая запись». Защитите эти две переменные с помощью мьютекса как у производителей, так и у потребителей, а затем используйте семафоры только для блокировки/запуска чтения и записи, как вы уже делаете. Если бы это было не школьное упражнение, вы могли бы лучше использовать одну переменную условия, связанную с мьютексом, о котором я упоминал. Когда он получает сигнал, родитель проверяет, может ли он писать, и дети проверяют, могут ли они читать. Когда происходит чтение или запись, сигнализируйте переменную состояния глобально, чтобы разбудить всех, чтобы проверить их условия. Это имеет то преимущество, что если у вас есть независимые слоты для буфера, тогда вы можете безопасно и счастливо одновременно использовать несколько потребителей.

1

No.

  1. писатель должен выпустить readSemaphore когда он написать одну единицу информации;
  2. автор должен приобрести allowedToRead блокировку (0,1 семафор - это блокировка/мьютекс) перед записью в общую память для предотвращения условий гонки.

Для упрощения: рассмотреть две функции read_shared_memory, write_shared_memory, которые являются для чтения и записи из/в совместно используемой памяти соответственно, и оба приобретающей/рилизинг того же замка перед чтением/записи.

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

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

Wikipedia описывает это более научным способом :)

Смежные вопросы