Общая переменная меняется только в одном процессе - PullRequest
0 голосов
/ 05 декабря 2018

У меня проблема в моем проекте для университета.У меня есть общая переменная с продуктами и количеством каждого продукта на складе.В интервалах «I» секунд есть запас Q в случайном произведении.Он отправляет сообщение для обработки «Склад», который добавляет это количество в общую память.В центре печатается продукт и его количество.Однако, в центре, количество всегда одинаково, и оно не увеличивается.Вот код:

//Struct for Shared Memory
typedef struct Warehouse{
    char name[50];
    int W_NO;
    pid_t pid;
    double x;
    double y;
    char products[3][50];
    int quantity[3];
}shared_mem;

//Struct for Message Queue
typedef struct Message_QUeue{

    long type;
    char product[50];
}message_queue;

shared_mem *shm;
int shmid;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void* receive_supply(void* id){
    int W_NO = *((int *)id);
    message_queue msg;
    while(1){
        //Receive messamge
        msgrcv(mq_id,&msg,sizeof(msg) - sizeof(long),1,0);
        for(int i = 0; i < (sizeof(shm.products)/sizeof(shm.products[0])); i++){  
            if(strcmp(msg.produto,shm.products[i]) == 0){ //Sees which product was randomizem
                pthread_mutex_lock(&mutex);
                shm.quantity[i] += Q;  //add quantity Q
                pthread_mutex_unlock(&mutex);   
                break;
            }
        }
    }
}

void warehouse(int W_NO){
    ids_supply[0] = W_NO;
    pthread_t supply;
    pthread_create(&supply,NULL,receive_supply,&W_NO);
}

void central(){
    while(1){
        for(int j = 0; j < (sizeof(shm.products)/sizeof(shm.products[0]));j++){
            printf("Warehouse: %d Quantity of product %s: %d\n",shm.W_NO,shm.products[j],shm.quantity[j]);
        }
        sleep(10);
    }
}

int main(){

    //Initialize shared memory
    if((shmid = shmget(IPC_PRIVATE,sizeof(shared_mem),IPC_CREAT | 0766)) < 0)
    {
      perror("Error in shmget with IPC_CREAT\n");
      exit(1);
    }

    if((shm = (shared_mem*)shmat(shmid, NULL, 0)) == (shared_mem*)-1)
    {
       perror("Shmat error");
       exit(1);
    }

    //Create process for Warehouse
    pid_t child_ID;
    switch(child_ID = fork()){
        case -1:
            printf("Error creating new process\n");
            break;
        case 0 :
            pthread_mutex_lock(&mutex);
            shm.W_NO = 1;
            pthread_mutex_unlock(&mutex);
            warehouse(1);
            exit(0);
            break;
        default:
            pthread_mutex_lock(&mutex);
            shm.pid = child_ID;
            shm.W_NO = 1;
            pthread_mutex_unlock(&mutex);
            break;
    }

    //Create Process Central
    id_central = fork();
    if (id_central == 0){
         central();
         exit(0);
    }

    srand(getpid());
    //send message to process Warehouse every S seconds with a random product
    while(1){
        message_queue msg;
        strcpy(msg.product,shm -> info_wh.produtos[rand()%(sizeof(shm.products)/sizeof(shm.products[0]))]);
        msg.type = 1;
        msgsnd(mq_id,&msg,sizeof(msg) - sizeof(long),0);
        sleep(S);
    }

Некоторые переменные, такие как Q, S, продукты и количество, взяты из текстового файла.Все это работает отлично, просто общая память не обновляется в центральном, и я не вижу, что не так.Любая помощь будет оценена.Код Soma может быть неправильным, потому что я взял его из исходного файла и попытался адаптировать его к этому посту.Если у вас есть какие-либо сомнения, не стесняйтесь спрашивать.

1 Ответ

0 голосов
/ 05 декабря 2018

Общая память создается ключом IPC_PRIVATE, что означает, что память является приватной для процесса.Дочерние процессы получают свою собственную копию этой памяти.

Вместо устаревших вызовов System V shmget и shmat делают один вызов:

shm = mmap(NULL, sizeof(shared_mem), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if(MMAP_FAILED == shm)
    perror('mmap');

Это создает анонимную память, котораясовместно используется родительским и его дочерними процессами.


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

...