2016-03-07 5 views
1

Расположение памяти разделено тремя процессами. Каждый процесс самостоятельно пытается увеличить содержимое места разделяемой памяти от 1 до определенного значения с шагом в один раз. У процесса 1 есть цель 100000, цель процесса 2 - 200000, а цель 3 - 300000. Если программа завершается, поэтому переменная общей памяти будет иметь в общей сложности 600000 (то есть это значение будет выводиться в зависимости от того, какой из трех процессов заканчивается последним). Я должен защитить критический раздел с помощью семафоров. Моя проблема в том, что у меня возникают проблемы с SETVAL для каждого процесса при инициализации семафора. Она хранит печать «Ошибка обнаружена в SETVAL», даже если у меня есть это значение 1. Правильный выход образца, а также мой код показан ниже:Семафоры с тремя процессами

Sample output 

From Process 1: counter = 100000. 
From Process 2: counter = 300000. 
From Process 3: counter = 600000. 

Child with ID 2412 has just exited. 
Child with ID 2411 has just exited. 
Child with ID 2413 has just exited. 

       End of Simulation. 



/*ass1*/ 

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/shm.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/sem.h> 

#define SEMKEY ((key_t) 400L) 
// number of semaphores being created 
#define NSEMS 2 

/* change the key number */ 
#define SHMKEY ((key_t) 7890) 


typedef struct 
{ 
    int value; 
} shared_mem; 

shared_mem *total; 

//structure 
int sem_id, sem_id2; 

typedef union{ 
    int val; 
    struct semid_ds *buf; 
    ushort *array; 
} semunion; 

static struct sembuf OP = {0,-1,0}; 
static struct sembuf OV = {0,1,0}; 
struct sembuf *P =&OP; 
struct sembuf *V =&OV; 
//function 
int Pop() 
{ 
    int status; 
    status = semop(sem_id, P,1); 
    return status; 
} 
int Vop() 
{ 
    int status; 
    status = semop(sem_id, V,1); 
    return status; 
} 




/*----------------------------------------------------------------------* 
* This function increases the value of shared variable "total" 
* by one with target of 100000 
*----------------------------------------------------------------------*/ 

void process1() 
{ 
    int k = 0; 

    while (k < 100000) 
    { 


     Pop(); 
     if (total->value < 600000) { 
     total->value = total->value + 1; 
     } 

     Vop(); 
     k++; 

    } 


    printf ("From process1 total = %d\n", total->value); 

} 


/*----------------------------------------------------------------------* 
* This function increases the vlaue of shared memory variable "total" 
* by one with a target 200000 
*----------------------------------------------------------------------*/ 

void process2() 
{ 
    int k = 0; 

    while (k < 200000) 
    { 


     Pop(); 
     if (total->value < 600000) { 
     total->value = total->value + 1; 
     } 

     Vop(); 
     k++; 
    } 

    printf ("From process2 total = %d\n", total->value); 

} 

/*----------------------------------------------------------------------* 
* This function increases the vlaue of shared memory variable "total" 
* by one with a target 300000 
*----------------------------------------------------------------------*/ 
void process3() 
{ 
    int k = 0; 

    while (k < 300000) 
    { 


    Pop(); 
    if (total->value < 600000) { 
     total->value = total->value + 1; 
    } 

    Vop(); 
    k++; 
    } 

    printf ("From process3 total = %d\n", total->value); 

} 


/*----------------------------------------------------------------------* 
* MAIN() 
*----------------------------------------------------------------------*/ 

int main() 
{ 
    int shmid; 
    int pid1; 
    int pid2; 
    int pid3; 
    int ID; 
    int status; 


    char *shmadd; 
    shmadd = (char *) 0; 

    //semaphores 
    int semnum = 0; 
    int value, value1; 
    semunion semctl_arg; 
    semctl_arg.val =1; 

    /* Create semaphores */ 
    sem_id = semget(SEMKEY, NSEMS, IPC_CREAT | 0666); 
    if(sem_id < 0) 
    printf("creating semaphore"); 

    sem_id2 = semget(SEMKEY, NSEMS, IPC_CREAT | 0666); 
    if(sem_id2 < 0) 
    printf("creating semaphore"); 

    /* Initialize semaphore */ 
    value1 =semctl(sem_id, semnum, SETVAL, semctl_arg); 

    value =semctl(sem_id, semnum, GETVAL, semctl_arg); 
    if (value < 1) 
    printf("Eror detected in SETVAL"); 




/* Create and connect to a shared memory segmentt*/ 

    if ((shmid = shmget (SHMKEY, sizeof(int), IPC_CREAT | 0666)) < 0) 
    { 
     perror ("shmget"); 
     exit (1); 
    } 


if ((total = (shared_mem *) shmat (shmid, shmadd, 0)) == (shared_mem *) -1) 
    { 
     perror ("shmat"); 
     exit (0); 
    } 


    total->value = 0; 

    if ((pid1 = fork()) == 0) 
    process1(); 

    if ((pid1 != 0) && (pid2 = fork()) == 0) 
    process2(); 

    if ((pid1 != 0) && (pid2 != 0) && (pid3 = fork()) == 0) 
    process3(); 


    waitpid(pid1, NULL, 0); 
    waitpid(pid2, NULL, 0); 
    waitpid(pid3, NULL, 0); 

    if ((pid1 != 0) && (pid2 != 0) && (pid3 != 0)) 
    { 
     waitpid(pid1); 
     printf("Child with ID %d has just exited.\n", pid1); 

     waitpid(pid2);  
     printf("Child with ID %d has just exited.\n", pid2); 

     waitpid(pid3); 
     printf("Child with ID %d has just exited.\n", pid3); 

     if ((shmctl (shmid, IPC_RMID, (struct shmid_ds *) 0)) == -1) 
    { 
     perror ("shmctl"); 
     exit (-1); 
    } 

     printf ("\t\t End of Program\n"); 

     /* De-allocate semaphore */ 
     semctl_arg.val = 0; 
     status =semctl(sem_id, 0, IPC_RMID, semctl_arg); 
     if(status < 0) 
     printf("Error in removing the semaphore.\n"); 
    } 

} 
+0

Извините за неоднозначность, отредактирован. – Antoninus

+0

Я пробовал код, и это сработало для меня. Я предлагаю вам проверить возвращаемое значение первого 'semctl'. Для обоих 'semctl', вы должны использовать' perror' для проверки 'errno', если return' -1'. – dancancode

+0

Это довольно странно, я снова запустил код, и это сработало, но когда я это сделал еще раз, я снова начал получать те же ошибки. В этих случаях возврат действительно равен -1. – Antoninus

ответ

2

Некоторые основы - ИНКЭМ длятся дольше, чем процесс, так как это было упомянутое использование ipcs и ipcrm для удаления ранее существовавших ipcs между прогонами. Убедитесь, что вы удалили ipcs после выполнения

waitpid(pid1, NULL, 0); 
waitpid(pid2, NULL, 0); 
waitpid(pid3, NULL, 0); 

Этот раздел предназначен для детей - они, вероятно, не должны.

total->value = total->value + 1; 

Безопасен IPC, поэтому могут возникать различные результаты (proc1 может перезаписывать приращение proc2).

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