2015-05-08 4 views
1

Я написал простую программу потребительского продюсера на C. Он отлично работает, пока у меня 1 производитель и 1 потребитель. Но это странно, когда я увеличиваю количество потребителей.Общая память и семафоры POSIX

  1. Я начинаю процесс продюсер
  2. Производитель производит
  3. Я начинаю процесс потребительского
  4. Потребитель трудоемкий и производитель производит
  5. Я не начать процесс интересов потребителей не процесс потребителей 2
  6. no2 никогда не получает элемент
  7. Когда я запускаю потребитель №3, №4 ... и так далее, то же самое происходит

Вторая проблема:

  1. Производитель произвел максимум элементов
  2. Потребитель потребляет все элементы, но производитель не продолжают производить больше

Я понятия не имею, почему это происходит.

Код:

Производитель:

#include <semaphore.h> 
#include <stdio.h> 
#include <errno.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/ipc.h> 
#include <sys/shm.h> 
#include <string.h> 
#include <fcntl.h> 
#include "common.h" 

int memoryID; 
struct wrapper *memory; 
int rc; 

void atexit_function() { 
    rc = shmctl(memoryID, IPC_RMID, NULL); 
    rc = shmdt(memory); 
    sem_destroy(&memory->pmutex); 
    sem_destroy(&memory->cmutex); 
    sem_destroy(&memory->empty); 
    sem_destroy(&memory->full); 
} 

int main(int argc, char **argv) { 
    atexit(atexit_function); 
    //creating key for shared memory 
    srand(time(NULL)); 
    key_t sharedMemoryKey = ftok(".", MEMORY_KEY); 
    if (sharedMemoryKey == -1) { 
     perror("ftok():"); 
     exit(1); 
    } 

    memoryID = shmget(sharedMemoryKey, sizeof(struct wrapper), IPC_CREAT | 0600); 
    if (memoryID == -1) { 
     perror("shmget():"); 
     exit(1); 
    } 

    memory = shmat(memoryID, NULL, 0); 
    if (memory == (void *) -1) { 
     perror("shmat():"); 
     exit(1); 
    } 

    //initialization 

    printf("Initializtaion !\n"); 
    memset(&memory->array, 0, sizeof(memory->array)); 
    sem_init(&memory->pmutex, 0, 1); 
    sem_init(&memory->cmutex, 0, 1); 
    sem_init(&memory->empty, 0, SIZE_OF_ARRAY); 
    sem_init(&memory->full, 0, 0); 
    memory->n = -1; 

    if (memoryID == -1) { 
     perror("shmget(): "); 
     exit(1); 
    } 


    while(1) 
    { 
     int r = rand(); 
     sem_wait(&memory->empty); 
     sem_wait(&memory->pmutex); 
     memory->n++; 
     (memory->array)[memory->n]=r; 
     printf("Adding task\t Value:%d\tNumber of tasks waiting:%d \n",r,memory->n); 
     usleep(10000); 
     sem_post(&memory->pmutex); 
     sem_post(&memory->full); 
    } 

} 

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

#include <semaphore.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include "common.h" 
#include <sys/shm.h> 

int memoryID; 
struct wrapper *memory; 
int check_prime(int a); 
int main(int argc, char **argv) { 
    srand(time(NULL)); 
    key_t sharedMemoryKey = ftok(".",MEMORY_KEY); 
    if(sharedMemoryKey==-1) 
    { 
     perror("ftok():"); 
     exit(1); 
    } 
    memoryID=shmget(sharedMemoryKey,sizeof(struct wrapper),0); 

    if(memoryID==-1) 
    { 
     perror("shmget(): "); 
     exit(1); 
    } 

    memory = shmat(memoryID,NULL,0); 
    if(memory== (void*)-1) 
    { 
     perror("shmat():"); 
     exit(1); 
    } 

    while(1) 
    { 
     sem_wait(&memory->full); 
     sem_wait(&memory->cmutex); 

     int n = memory->n; 
     int temp = (memory->array)[n]; 
     printf("Removed item: %d\tPrime:%d\tNumer of tasks left:%d\n", 
      temp, check_prime(temp),n); 
     memory->n--; 
     usleep(10000); 

     sem_post(&memory->cmutex); 
     sem_post(&memory->empty); 
    } 

} 

common.h:

#define MEMORY_KEY 12 
#define SIZE_OF_ARRAY 10 
struct wrapper 
{ 
    int array[SIZE_OF_ARRAY]; 
    sem_t empty; 
    sem_t pmutex; 
    sem_t cmutex; 
    sem_t full; 
    int n; 
}; 
+0

Я думаю, вы должны оставить время для другого процесса, чтобы принять РЭМ. Например. спать, пока 1 после семестра. – LPs

+0

К сожалению, это не помогает –

+0

опубликованный код кажется излишне сложным. Кажется, что нет никакой нулевой потребности для любого семафора. Для данных нужны мьютекс, счетчик и массив. потребители должны спать ненадолго, когда объект/int не может обрабатываться. Продюсеру нужно немного поспать, когда массив заполнен. Я бы также предложил, чтобы старые данные не обрабатывались своевременно, чтобы массив рассматривался как круговой список с указателем головы и хвоста – user3629249

ответ

1

Проблема решена. я садился int sem_init(sem_t *sem, int pshared, unsigned int value); я садился pshared значения 0, но:

The pshared argument indicates whether this semaphore is to be shared between the 
    threads of a process, or between processes. 

    If pshared has the value 0, then the semaphore is shared between the threads of a 
    process, and should be located at some address that is visible to all threads (e.g., a 
    global variable, or a variable allocated dynamically on the heap). 

    If pshared is nonzero, then the semaphore is shared between processes, and should be 
    located in a region of shared memory (see shm_open(3), mmap(2), and shmget(2)). (Since 
    a child created by fork(2) inherits its parent's memory mappings, it can also access 
    the semaphore.) Any process that can access the shared memory region can operate on 
    the semaphore using sem_post(3), sem_wait(3), etc. 
Смежные вопросы