2013-03-27 2 views
0

Я использую семафоры с разделяемой памятью для связи между несколькими производителями и несколькими клиентами. В моей системе есть два основных вида семафоров, которые представляют собой «хранимые семафоры» и «обработанные семафоры».как эффективно подождать на семафоре?

Система работает следующим образом: Производители непрерывно помещают данные в общую память, а затем увеличивают значение хранимого семафора, в то время как потребители находятся в цикле, ожидая таких хранящихся семафоров. Потребители после получения данных от производителя будут обрабатывать такие данные, а затем увеличивают значение обработанного семафора. Производители получат свои результаты, ожидая «обработанного семафора»

Код производителя:

for(int i =0;i<nloop;i++){ 
    usleep(100); 
    strcpy(shared_mem[i], "data for processing"); 
    sem_post(&shared_mem[i].stored_semaphored); 
    if(sem_timedwait(&msg_ptr->processed_semaphore,&ts)==-1){ //waiting for result 
     if(errno == ETIMEDOUT){ 
     } 
     break; 
    }else{ 
     //success 
    } 

} 

код потребителя:

for (int j = 0; j < MAX_MESSAGE; j++) { 
if (sem_trywait(&(shm_ptr->messages[j].stored_semaphore)) == -1) { 
    if (errno == EAGAIN) { 
    } else { 
      //success ==> process data 
      //post result back on the shared memory, and increase       
      //the processed semahore 
     strcpy(shared_mem[j].output, "Processed data"); 
     sem_post(&(shared_mem[j].processed_semaphore)); 
    } 
} 
}//for loop over MAX_MESSAGE 

Моя проблема заключается в том, что цикл в потребительском код теряя почти 100% процессор, потому что в случае отсутствия данных от производителя это для цикла работает непрерывно.

Мой вопрос в том, что существуют другие способы ожидания на множестве семафоров (что может быть похоже на механизм ожидания SELECT, POLL или EPOLL), что не переносит процессорное время.

Надеюсь на ваш ответ. Спасибо!

+0

Общий пул ресурсов должен управляться одним семафором, а не набором. –

ответ

1

Насколько я знаю, нет способа ждать на семафорах. Это означает, что все обращения должны направляться через один семафор. Вы перебираете набор семафоров, поэтому вместе они могут стать одним объектом. Этот потребитель должен знать, когда какой-либо из семафоров был сигнализирован, поэтому используйте дополнительный sem_post на новом семафоре, чтобы сигнализировать о смене набора семафоров.

Ваш код производителя становится чем-то вроде этого:

.... 
sem_post(&shared_mem[i].stored_semaphored); 
sem_post(&list_changed_semaphore); /* Wake the consumer. */ 
.... 

и потребитель:

/* Block until a consumer has indicated that it has changed the semaphore list */ 
if (!sem_wait(&list_changed_semaphore)) { 
    /* At least one producer has signalled a change. */ 
    for (int j = 0; j < MAX_MESSAGE; j++) { 
     if (sem_trywait(&(shm_ptr->messages[j].stored_semaphore)) == -1) { 
     } 
    } 
} 

Вместо того, чтобы использовать семафор для list_changed_semaphore вы можете использовать переменную в pthread_cond_t условие, чтобы сигнализировать, что что-то в вашей набор семафоров изменился. list_changed_semaphore не обязательно должен быть счетчиком в качестве примера, показанного здесь, он должен быть только одним битом, чтобы указать, что производитель изменил список.

+0

Pillips: Спасибо за ваш продуманный ответ! Это решило мою проблему. – khanhhh89

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