2017-06-04 3 views
0

Donc, j'écris actuellement un programme client/serveur qui va prendre trois commandes (HI, PID et GOODBYE) et les traiter en conséquence. Je semble avoir rencontré quelques problèmes avec mon utilisation de semget() dans mon code server.c.Essayer d'utiliser semget() pour obtenir un ensemble de sémaphores mais je reçois toujours une erreur EEXIST, même après avoir créé une nouvelle clé

L'erreur que je reçois est "EEXIST", qui, selon les pages man, dit que la clé existe déjà (duh lol) - la chose est, je continue à changer manuellement la clé à chaque fois et il donne encore moi l'erreur. Est-ce que je ne comprends pas quelque chose ici? Il semble également fonctionner correctement pour le code client.c. Est-ce que l'un d'entre vous a une idée de pourquoi je ressens cela? Désolé pour le code un peu bâclé, je me suis cassé la tête sur mon clavier toute la nuit, je ferai de mon mieux pour commenter mes processus de pensée. Faites-moi savoir s'il y a quelque chose que je peux faire pour le rendre plus facile à lire.

client.c:

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

#define MEM_KEY 99 // memory key 
#define SEM_KEY 1337 // semaphore key 
#define SEG_SIZE ((size_t)100) // segment size 
#define oops(m, x) { perror(m); exit(x); } // for error checking 
int seg_id, semset_id; 
union semun{ int val; struct semid_ds* buf; ushort* array; }; // for wait and release functions 
void wait_and_lock(int); 
void release_lock(int); 

int main() 
{ 
    char c; 
    key_t memKey = MEM_KEY, semKey = SEM_KEY; // not sure if this is necessary 
    char *memPtr; 

    if ((seg_id = shmget(memKey, SEG_SIZE, IPC_CREAT | 0777)) < 0) // get segment ID 
     oops("shmget", 1); 

    if ((memPtr = shmat(seg_id, NULL, 0)) == (char *) -1) // attach the memory segment 
     oops("shmat", 2); 

    semset_id = semget(semKey, 2, (0666 | IPC_CREAT | IPC_EXCL)); // for some reason I couldn't include this in an if-statement 
    // but it seems to work here in the server code 
    if (semset_id == -1) 
     oops("semset", 2.5); 

    wait_and_lock(semset_id); // this function was something our teacher went over with us. 
    // I'm still a little confused with what it's doing. 
    while(1) 
    { 
     printf("enter: "); // get the commands, is there a better way of doing this? 
     scanf("%s", memPtr); 
    } 

    release_lock(semset_id); 

    while (*memPtr != '*') // not sure if this is necessary, left over from old code that I was experimenting with. 
     sleep(1); 

    shmdt(memPtr); // detach the memory 

    exit(0); 
} 

void wait_and_lock(int semset_id) 
{ 
    union semun sem_info;      // some properties 
    struct sembuf actions[2];     // action set, an array 

    actions[0].sem_num = 1;     // sem[1] is n_writers 
    actions[0].sem_flg = SEM_UNDO;   // auto cleanup 
    actions[0].sem_op = 0;     // wait for 0 
    actions[1].sem_num = 0;     // sem[0] is n_readers 
    actions[1].sem_flg = SEM_UNDO;   // auto cleanup 
    actions[1].sem_op = 1;     // incr n_readers 

    if (semop(semset_id, actions, 2) == -1) 
     oops("semop: locking", 10); 
} 

void release_lock(int semset_id) 
{ 
    union semun sem_info;      // some properties 
    struct sembuf actions[1];     // action set 

    actions[0].sem_num = 0;     // sem[0] is n_readers 
    actions[0].sem_flg = SEM_UNDO;   // auto cleanup 
    actions[0].sem_op = -1;     // decr reader country 

    if (semop(semset_id, actions, 1) == -1) 
     oops("semop: unlocking", 10); 
} 

server.c:

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

#define MEM_KEY 99 
#define SEM_KEY 1337 
#define SEG_SIZE ((size_t)100) 
#define oops(m, x) { perror(m); exit(x); } 

union semun { int val; struct semid_ds* buf; unsigned short* array; }; 
int seg_id, semset_id; 
void cleanup(int); 
void set_sem_value(int, int, int); 
void wait_and_lock(int); 
void release_lock(int); 

int main() 
{ 
    int id = 0; 
    char *memPtr; 
    key_t memKey = MEM_KEY, semKey = SEM_KEY; 

    signal(SIGINT, cleanup); // to handle Ctrl-C 

    seg_id = shmget(memKey, SEG_SIZE, 0777); // get segment ID 
    if(seg_id == -1) 
     oops("shmget", 1); 

    if ((memPtr = shmat(seg_id, NULL, 0)) == (char *) -1) // attach to memPtr 
     oops("shmat",2); 

    semset_id = semget(semKey, 2, (0666 | IPC_CREAT | IPC_EXCL)); 
    // this is where there seems to be an issue? This is where the code stops. 
    if (semset_id == -1) 
     oops("semget", 3); 

    set_sem_value(semset_id, 0, 0); // set counters 
    set_sem_value(semset_id, 1, 0); // both to zero 

//Now read what the client put in the memory (still not sure if this works 
//because the program hasn't technically gotten that far. So this while loop is more 
//of a prototype). 
    while(1) 
    { 
     wait_and_lock(semset_id); 

     printf("\tshm_ts2 update memory\n"); // will be removed at the end 
     sleep(1); 
     if(strcmp(memPtr, "HI")==0) // look for HI 
     { 
      printf("Greetings!\n"); // print this to the server screen 
      fflush(stdout); 
      memPtr[0] = '\0'; 

     } 
     else if(strcmp(memPtr, "PID")==0) // look for PID and get server's PID 
     { 
      id = (int)getpid(); 
      printf("Server pid: %i\n", id); 
      fflush(stdout); 
      memPtr[0] = '\0'; 

     } 
     else if(strcmp(memPtr, "QUIT")==0){ // check for quit 
      shmctl(seg_id, IPC_RMID, NULL); // mark seg to be destroyed 
      shmdt(memPtr); // detach segment 
      printf("GOODBYE!\n"); 
      exit(0);  
     } 
     release_lock(semset_id); 
     printf("\tshm_ts2 released lock\n"); // will be removed at the end 
    } 

    *memPtr = '*'; // still not sure if this is necessary, from old code 
    cleanup(0); 
    return 0; 

} 

void cleanup(int n) 
{ 
    shmctl(seg_id, IPC_RMID, NULL); 
    semctl(semset_id, 0, IPC_RMID, NULL); 
} 


void set_sem_value(int semset_id, int semnum, int val) 
{ 
    union semun initval; 

    initval.val = val; 

    if (semctl(semset_id, semnum, SETVAL, initval) == -1) 
     oops("semctl", 4); 
} 


void wait_and_lock(int semset_id) 
{ 
    struct sembuf actions[2];     // action set, an array 

    actions[0].sem_num = 0;     // sem[0] is n_readers 
    actions[0].sem_flg = SEM_UNDO;   // auto cleanup 
    actions[0].sem_op = 0;     // wait til no readers 
    actions[1].sem_num = 1;     // sem[1] is n_writers 
    actions[1].sem_flg = SEM_UNDO;   // auto cleanup 
    actions[1].sem_op = 1;     // increment number of writers 

    if (semop(semset_id, actions, 2) == -1) 
     oops("semop: locking", 10); 
} 

// Thing 4: build and execute a 1-element action set: decrement num_writers 
void release_lock(int semset_id) 
{ 
    struct sembuf actions[1];     // action set, an array 
    actions[0].sem_num = 1;     // sem[0] is n_writers 
    actions[0].sem_flg = SEM_UNDO;   // auto cleanup 
    actions[0].sem_op = -1;     // decrement number of writer count 

    if (semop(semset_id, actions, 1) == -1) 
     oops("semop: unlocking", 10); 
} 
+0

Veuillez fournir [mcve]. –

+0

Alors, quel est le problème ici? n'est-ce pas minimal? Je me sens comme enlever tout ce qui pourrait rendre difficile de repérer le problème? Je suppose que je pourrais enlever le client.c puisque le serveur a le plus de problèmes? Le simple fait de lier cette page ne m'aide pas du tout. @PasserBy – terpy

+0

Vous pouvez relire la page de manuel sur 'shmctl()' et lire la page man sur 'shmdt()' – user3629249

Répondre

0

Vous devez faire un système de clé V IPC en utilisant la fonction ftok. Que, cette clé doit être passée en tant que premier paramètre à l'appel système shmget. La même chose s'applique aux sémaphores. Créez une clé IPC System V en utilisant ftok et passez-la comme premier paramètre à semget.