1

我正在使用带有共享内存的信号量在多生产者和多客户端之间进行通信。我的系统中有两种主要的信号量,分别是“存储的信号量”和“处理的信号量”。

系统运行如下:生产者不断地将数据放入共享内存,然后增加存储的信号量的值,而消费者则在循环中,等待存储的信号量。消费者在收到生产者的数据后,会对这些数据进行处理,然后增加处理后的信号量的值。生产者将通过等待“已处理的信号量”来获得结果

生产者代码:

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

我的问题是消费者代码中的 for 循环几乎浪费了 100% 的 CPU,因为在没有来自生产者的数据的情况下,这个 for 循环会连续运行。

我的问题是,还有其他方法可以等待一组信号量(可能类似于 SELECT、POLL 或 EPOLL 的等待机制),这不会浪费 CPU 时间。

希望看到你的回答。非常感谢!

4

1 回答 1

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显示的示例那样是计数器,它只需要一个位即可指示生产者已修改列表。

于 2013-03-27T06:03:00.117 回答