Matthew.J
Matthew.J

Reputation: 65

c semaphores and shared memory action counter

I am working with semaphores and shared memory. I need create 11 subprocesses. First with I=0 is printing A and others are printing B. Then I need each proces to print message with counter *APtr so there will be lines on output with numbers 1-11 followed by proces signification and final value of *APtr on last row which should be 12.

Now its not working. Processes are writing and reading *APtr at the same time so i get output with first numbers for example 1, 1, 1, 4, 5, 6, 7, 7, 8, 8, 11, 12

int I, A;
int *APtr;
//create shared memory (action counter)
if((A=shmget(ftok(argv[0],getpid()), sizeof(int),  IPC_CREAT | 0660)) == -1)
{
    exit(2);
}
if((APtr=shmat(A,NULL,0)) == NULL)
{
    exit(2);
}
*APtr = 1;


/*semaphor semA*/
sem_t semA;
if(sem_init(&semA, 0, 1)==-1)
{
    exit(2);
}
/*semafor semA*/
pid_t pid;
for(int i=0; i<11; ++i)
{
    if((pid = fork()) < 0)
    {     //chyba spusteni noveho procesu
        kill(0, SIGTERM);
        exit(2);
    }
    else if(pid == 0)
    {
        I=i;
        if(I == 0)//A
        {
            sem_wait(&semA);
            //int pom = *APtr;
            fprintf(stdout, "%d: A %d:\n", *APtr, I);
            fflush(stdout);
            *APtr+=1;
            sem_post(&semA);
        }
        else//B
        {
            sem_wait(&semA);
            //int pom = *APtr;
            fprintf(stdout, "%d: B %d:\n", *APtr, I);
            fflush(stdout);
            *APtr+=1;
            sem_post(&semA);
        }
        break;
    }
    else
    {
        //fprintf(stdout, "%d\n", *APtr);
    }
}
sem_destroy(&semA);
if(pid != 0)
{
    sleep(1);
    fprintf(stdout, "%d\n", *APtr);
}
return 0;

If i understand it correctly sem_init(&semA, 0, 1); should initialize semaphor to allow only one proces work after sem_wait(&semA); until sem_post(&semA); command is done. So what am I doing/understanding wrong?


After switching to sem_open() i got returnded NULL and all forked processes crash on sem_wait() there is my new code.

int I, A;
int *APtr;
//create shared memory (action counter)
if((A=shmget(ftok(argv[0],getpid()), sizeof(int),  IPC_CREAT | 0660)) == -1)
{
    exit(2);
}
if((APtr=shmat(A,NULL,0)) == NULL)
{
    exit(2);
}
*APtr = 1;


/*semaphor semA*/
sem_t *semA;
if(semA = sem_open("/semA", O_CREAT, 0700, 1) == SEM_FAILED)
{
    exit(2);
}
/*semafor semA*/
pid_t pid;
for(int i=0; i<11; ++i)
{
    if((pid = fork()) < 0)
    {     //chyba spusteni noveho procesu
        kill(0, SIGTERM);
        exit(2);
    }
    else if(pid == 0)
    {
        I=i;
        if(I == 0)//A
        {
            sem_wait(semA);
            fprintf(stdout, "%d: A %d:\n", *APtr, I);
            fflush(stdout);
            *APtr+=1;
            sem_post(semA);
        }
        else//B
        {
            sem_wait(semA);
            fprintf(stdout, "%d: B %d:\n", *APtr, I);
            fflush(stdout);
            *APtr+=1;
            sem_post(semA);
        }
        break;
    }
    else
    {
        //fprintf(stdout, "%d\n", *APtr);
    }
}
if(pid != 0)
{
    sleep(1);
    sem_close(semA);
    fprintf(stdout, "%d\n", *APtr);
}
return 0;

Upvotes: 0

Views: 1994

Answers (2)

Matthew.J
Matthew.J

Reputation: 65

It was missing braces:

if((semA = sem_open("/semA123", O_CREAT, 0700, 1)) == SEM_FAILED)

Upvotes: 0

nos
nos

Reputation: 229204

sem_t semA;
if(sem_init(&semA, 0, 1)==-1)

Your semaphore here is not in shared memory, it lives on the stack.

So after you fork(), each process will have its own copy of this semahore. You should place the semahore somewhere in the shared memory you've created so all processes can access the same semaphore.

Instead of sem_init() you could use sem_open() to create a named semahore, which are shared among whoever have it opened.

Upvotes: 1

Related Questions