简体   繁体   中英

Semaphores only working at the end

I've got a weird problem with my code. It is suppoused to use Linux Semaphores to prevent 3 "trains" to enter the track at the same time. so the output must be something like: Entra Peru Sale Peru Entra Bolivia Sale Bolivia Entra Colombia Sale Colombia ... (10 times)

And it doesent, first enter the 3 of them and then the 3 of them get out. But, at the last cycle it works as it should. So, any ideas? Heres the source code:

/*semaphore.h*/
struct sembuf {
   ushort  sem_num;        /* semaphore index in array */
   short   sem_op;         /* semaphore operation */
   short   sem_flg;        /* operation flags */
};


int seminit(int idsem, int value){
   int semid = semget(idsem, 1, IPC_CREAT);
   return semid;
}

void semwait(int idsem){
  int semid = semget(idsem, 0, IPC_EXCL);
  struct sembuf sops={semid, -1, 1};

  int op = semop (semid, sops, 1);
}

void semsignal(int idsem){
  int semid = semget(idsem, 0, IPC_EXCL);
  struct sembuf sops={semid, 1, 1};
  int op = semop (semid,sops, 1);
}

And this:

/*semaforos.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include "semaphores.h"

#define CICLOS 10


char *pais[3]={"Peru","Bolivia","Colombia"};

int *g;

void proceso(int i)
{
   int k;
   int l;

   int semid=seminit(i, -1);
   printf("\nSEMID: %d\n",semid);
   for(k=0;k<CICLOS;k++)
   {
      semwait(i);
   //Entrada a la seccción crítica
      printf("Entra %s\n",pais[i]);
      fflush(stdout);
      sleep(rand()%3);
      printf("- %s Sale\n",pais[i]);
      semsignal(i%3);
   // Salida de la sección crítica
      sleep(rand()%3);   // Espera aleatoria fuera de la sección crítica
   }
   exit(0); // Termina el proceso
}

int main()
{
   int pid;
   int status;
   int args[3];
   int i;
   srand(getpid());
   for(i=0;i<3;i++)
   {
      pid=fork(); // Crea un nuevo proceso hijo que ejecuta la función proceso()
      if(pid==0)
         proceso(i);
   }

   for(i=0;i<3;i++)
      pid = wait(&status);
 }

To make the semaphore work correctly, the code should create one semaphore, and use that semaphore for all three processes. Your code seems to create a separate semaphore for each process. Also, after creating the semaphore, the code should initialize the value of the semaphore to 1, so that the semaphore is ready to be taken.

Here's how I would write the code

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

#define SEM_RA    (SEM_R | SEM_A)
#define SEM_FLAGS (SEM_RA | (SEM_RA >> 3) | (SEM_RA >> 6))
#define CICLOS 10

static void error( const char *msg )
{
    perror( msg );
    exit( 1 );
}

void waitSem( int semid, int semnum )
{
    struct sembuf operations = { semnum, -1, 0 };

    if ( semop( semid, &operations, 1 ) < 0 )
        error( __func__ );
}

void signalSem( int semid, int semnum )
{
    struct sembuf operations = { semnum, 1, 0 };

    if ( semop( semid, &operations, 1 ) < 0 )
        error( __func__ );
}

void proceso( char *pais, int semID )
{
    int k;

    for ( k = 0; k < CICLOS; k++ )
    {
        waitSem( semID, 0 );
        // Entrada a la sección crítica
        printf( "Entra %s ", pais );
        fflush( stdout );
        sleep( arc4random_uniform( 3 ) );   // Espera aleatoria dentro de la sección crítica
        printf("- %s Sale\n", pais );
        signalSem( semID, 0 );
        // Salida de la sección crítica
        sleep( arc4random_uniform( 3 ) );   // Espera aleatoria fuera de la sección crítica
    }

    exit(0); // Termina el proceso
}

char *paises[3] = { "Peru", "Bolivia", "Colombia" };

int main( void )
{
    int i, semID, status;
    pid_t pid;

    // create the one semaphore that will be used by all three child processes
    if ( (semID = semget( 0x1001, 1, IPC_CREAT | SEM_FLAGS )) < 0 )
        error( "Unable to create semaphore" );

    // set the semaphore count to 1 so it's ready to be taken
    if ( semctl( semID, 0, SETVAL, 1 ) < 0 )
        error( "Unable to initialize semaphore" );

    for ( i = 0; i < 3; i++ )
    {
        pid = fork();       // Crea un nuevo proceso hijo que ejecuta la función proceso()
        if ( pid == 0 )
            proceso( paises[i], semID );
    }

    for ( i = 0; i < 3; i++ )
        wait( &status );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM