tags:

views:

248

answers:

1

Hi, all

I'm writing a program with two processes operate on a semaphore in the ping-pong mode. The program first calls semget() to acquire a semaphore of size 2, semaphore #0 is initialized with value 1 while semaphore #1 is initialized with value 0. The code is as following:

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

static int
ping(int semid)
{
    struct sembuf ops[2];
    int ret;

    ops[0].sem_num = 0;
    ops[0].sem_op = -1;
    ops[0].sem_flg = 0;
    ops[1].sem_num = 1;
    ops[1].sem_op = 1;
    ops[1].sem_flg = 0;
    ret = semop(semid, ops, 2);

    if (ret) {
        perror("ping");
        exit(-1);
    }
    return 0;
}

static int
pong(int semid)
{
    struct sembuf ops[2];
    int ret;

    ops[0].sem_num = 0;
    ops[0].sem_op = 1;
    ops[0].sem_flg = 0;
    ops[1].sem_num = 1;
    ops[1].sem_op = -1;
    ops[1].sem_flg = 0;
    ret = semop(semid, ops, 2);

    if (ret) {
        perror("pong");
        exit(-1);
    }
    return 0;
}

int
main(int argc, char *argv[])
{
    int semid;
    key_t semkey;
    pid_t pid;
    int i;

    if (argc > 1) {
        semkey = atoi(argv[1]);
        semid = semget(semkey, 2, 0666);
    } else {
        semkey = 1001;
        if ((semid = shmget(semkey, 2, 0666 | IPC_CREAT)) < 0)
            exit(-1);
        /* Init semephore array with {1, 0}, so the ping process will run first */
        semctl(semid, 0, SETVAL, 1);
        semctl(semid, 1, SETVAL, 0);
    }

    printf("pingpong begin with semkey=%d, semid=%d\n", semkey, semid);
    pid = fork();
    if (pid == 0) {
        for (i = 0; i < 10; i++) {
            printf("ping\n");
            ping(semid);
        }
    } else {
        for (i = 0; i < 10; i++) {
            printf("pong\n");
            pong(semid);
        }
    }

    return 0;
}

$ ./pingpong
pingpong begin with semkey=1001, semid=2490371
ping
ping: Invalid argument
pong
pong: Invalid argument

And in the manpage it says the error code of semop is EINVAL when the value of semid is not a valid semaphore identifier, or the number of individual semaphores for which the calling process requests a SEM_UNDO would exceed the system-imposed limit. But I still can't figure it out why the operations fail.

+4  A: 

Looks like the problem is a typo here:

    if ((semid = shmget(semkey, 2, 0666 | IPC_CREAT)) < 0)
                 ^^^^^^

...should be semget().

Matthew Slattery
Thanks for that :P
ZelluX