信号量只在最后工作

时间:2014-10-30 22:45:27

标签: c linux semaphore

我的代码遇到了一个奇怪的问题。它被允许使用Linux信号量来防止3" train"同时进入赛道。所以输出必须是这样的: Entra秘鲁 出售秘鲁 恩特拉玻利维亚 销售玻利维亚 恩特拉哥伦比亚 销售哥伦比亚 ... (10次)

然后它首先进入其中的3个,然后其中3个退出。但是,在最后一个循环中它可以正常工作。那么,有什么想法吗?下面是源代码:

/*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);
}

而且:

/*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);
 }

1 个答案:

答案 0 :(得分:0)

要使信号量正常工作,代码应创建一个信号量,并将该信号量用于所有三个进程。您的代码似乎为每个进程创建一个单独的信号量。此外,在创建信号量之后,代码应该将信号量的值初始化为1,以便准备好采用信号量。

这是我如何编写代码

#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 );
}