0

I don't really understand how shared memory works and I am trying to write a server-client program in which the server and client talk to each other using shared memory and semaphores.

Shared memory structure:

typedef struct shared_mem{
    int board[BOARD_SIZE * BOARD_SIZE];
    int goal;
    int client;
    int direction;
    sem_t sem_server;
}shared_mem;
shared_mem *msg;

Server:

int shmid;
key_t key=ftok("2048_client.c", 42);
if(key == -1) {
        printf("ftok failed");
        return -1;
    }
shared_mem *shm;

    if ((shmid = shmget(key, sizeof(msg), IPC_CREAT|0600)) < 0) {
        perror("shmget");
        exit(1);
    }

if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
        perror("shmat");
        exit(1);
    }

msg=shm;

int direction = -1;
srand(time(NULL));

//SERVER SETS VALUES FOR SHARED MEMORY STRUCTURE

sem_wait(&msg->sem_server);

// setup the board
initialize();

// the board starts with 2 pieces
create_game_piece();
printf("pieces created");
create_game_piece();

msg->client=0;

int i;

for (i = 0; i < BOARD_SIZE * BOARD_SIZE; i++)
    msg->board[i] = board[i];

sem_post(&msg->sem_server);     

// game loop
while (1) {

    //CLIENT READS AND CHANGES VALUES

    //SERVER READS VALUES CHANGED BY CLIENT

    if (!move_board(direction))
        continue;

    sem_wait(&msg->sem_server);
    moves++;
    direction=msg->direction;

    if (check_win()) {
        print_board(-1);
        printf("congratulations! you've won in %d moves\r\n", moves);
        return 0;
    }

    create_game_piece();

    if (!has_moves_left()) {
        print_board(-1);
        printf("you lose! try again\r\n");
        //sleep(1);
        return 1;
    }
    sem_post(&msg->sem_server); 
}

Client:

int shmid;
key_t key=ftok("2048_client.c", 42);
if(key == -1) {
        printf("ftok failed");
        return -1;
    }
shared_mem *shm;
msg=(shared_mem *)malloc(sizeof(shared_mem));

    if ((shmid = shmget(key, sizeof(msg), IPC_CREAT|0600)) < 0) {
        perror("shmget");
        exit(1);
    }

  if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
        perror("shmat");
        exit(1);
    }

atexit(on_exit2);
system("stty raw");

srand(time(NULL));

while (1) {

    // CLIENT READS VALUES CHANGED BY SERVER AND CHANGES THEM

    sem_wait(&msg->sem_server); 
    print_board(direction);

    direction = keypress();
    msg->direction=direction;
    sem_post(&msg->sem_server); 
}

Could someone please tell me how to coordinate the way the client and server access the shared memory so that it works according to the comments in the code?

0

2 Answers 2

1

SHM_UNLOCK does not do what you think. It tries to lock pages in memory not prevent access. You need a semaphore to control access to the shared memory. See semctl, semget, etc., and employ them in both the client and server for mutually exclusive access.

Sign up to request clarification or add additional context in comments.

4 Comments

Added semaphores but I still think I'm doing something wrong because it still doesn't work as intended.
I don't see where you create/init the semaphore. (1) Are client & server unrelated pgms or forked? (2) Did you use sem_init or sem_open?
Please don't avocate to use semctl/semget and friends - they're the 'old interface'. Use the newer POSIX interface sem_init/sem_post/sem_wait, which is a lot less cumbersome to use.
@Klaas van Gend, OP is already using sysV shared memory and while I (normally) prefer and recommend the posix interface sysV semaphores do have features unavailable in the posix ipc family. They aren't going away.
1

There are a lot of things wrong with your code.

  • You did not initialize the semaphore at all. For this operation where the semaphore is located in shared memory, make sure to set the pshared argument to nonzero.
  • You cannot do two-way synchronization this way with only one semaphore (otherwise you do a sem_post, that is immediately sem_waited by the same process, hence that thread may continue, the other one doesn't get to run).
  • You malloc'ed msg in the client, and never pushed it to the shared memory, thus the shared memory is still not initialized.
  • What do you think system("stty raw") is going to accomplish, other than opening a seriously big can of security issues?
  • Obviously it wasn't runnable code. I've fixed quite a few small things, but gave up after half an hour because there's just too much wrong with it. Things like comparing a char* to a shared_mem* is wrong. Enable -Wall and -Wextra on your compiler and fix all warnings you get. Your code is full of it and unfortunately all indicate serious issues.

From a design perspective, there are even more issues.

Apparently you are using a 1-D array 'board' that is global in the server. This is not proper for two reasons:

  • The board is always 2-dimensional, why not use a 2D array?
  • You use it as a global variable, accessible by all functions. This is "javascript"-style programming. Please make the board local to main and pass it to the various functions.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.