現在、私は3つのコマンド(HI、PID GOODBYE)を作成し、それに応じて処理します。私は私のserver.cコードでsemget()を使用していくつかの問題に遭遇したようです。semget()を使用してセマフォセットを取得しようとしましたが、新しいキーを作成してもEEXISTエラーが発生します
私が得ているエラーは、マニュアルページによると、キーがすでに存在していると言われている「EEXIST」です。つまり、毎回手動でキーを変更せず私はエラーです。私はここで何かを理解していないのですか?また、client.cコードでうまく動作しているようです。なぜ私がこれを体験しているのか、皆さんの考えがありますか?
申し訳ありませんが、やや汚れたコードでは、私は徹夜でキーボードを叩いていましたが、思考過程をコメントアウトするために全力を尽くします。読みやすくするためにできることがあれば教えてください。
いる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);
}
[mcve]を入力してください。 –
ここで問題は何ですか?最小ではないですか?私は何かを取り除くことが問題を見つけるのを難しくするかもしれないように感じる?私は、サーバが最も問題を抱えているので、私はclient.cを取り除くことができたと思いますか?そのページをリンクするだけでは何の助けにもなりません。 @PasserBy – terpy
ouは 'shmctl()'のmanページを再読み込みし、 'shmdt()'のmanページを読みたいかもしれません。 – user3629249