Семафоры с тремя процессами

Место в памяти совместно используется тремя процессами. Каждый процесс независимо пытается увеличить содержимое ячейки общей памяти с 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");
    }

} 

person KoolaidLips    schedule 07.03.2016    source источник
comment
Извините за двусмысленность, отредактировано.   -  person KoolaidLips    schedule 07.03.2016
comment
Я попробовал код, и он сработал для меня. Я предлагаю вам проверить возвращаемое значение первого semctl. Для обоих semctl вы должны использовать perror для проверки errno, если возвращается -1.   -  person dan4thewin    schedule 07.03.2016
comment
Это довольно странно, я снова запустил код, и он сработал, но когда я сделал это еще раз, я снова начал получать те же ошибки. В этих случаях возврат действительно равен -1.   -  person KoolaidLips    schedule 07.03.2016
comment
Вас могут заинтересовать ipcs и ipcrm. Кроме того, немного странно вызывать semget дважды с одним и тем же ключом и IPC_CREAT. Не уверен, что вы пытались там сделать.   -  person user3386109    schedule 07.03.2016


Ответы (1)


Некоторые основы — IPC длятся дольше, чем процесс, поэтому, как уже упоминалось, используйте ipcs и ipcrm для удаления ранее существовавших IPC между запусками. Убедитесь, что вы удалили ipcs после выполнения

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

Этот раздел будет создан для детей — вероятно, им не следует этого делать.

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

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

person mksteve    schedule 07.03.2016