2017-06-04 19 views
0

現在、私は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); 
} 
+0

[mcve]を入力してください。 –

+0

ここで問題は何ですか?最小ではないですか?私は何かを取り除くことが問題を見つけるのを難しくするかもしれないように感じる?私は、サーバが最も問題を抱えているので、私はclient.cを取り除くことができたと思いますか?そのページをリンクするだけでは何の助けにもなりません。 @PasserBy – terpy

+0

ouは 'shmctl()'のmanページを再読み込みし、 'shmdt()'のmanページを読みたいかもしれません。 – user3629249

答えて

0

あなたはftok関数を使用して、システムV IPCキーを作成する必要があります。それよりも、そのキーは最初のパラメータとしてshmgetシステムコールに渡されるべきです。セマフォにも同じことが言えます。 ftokを使用してSystem V IPCキーを作成し、それをsemgetの最初のパラメータとして渡します。

関連する問題