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);
}
Veuillez fournir [mcve]. –
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
Vous pouvez relire la page de manuel sur 'shmctl()' et lire la page man sur 'shmdt()' – user3629249