【问题标题】:Trying to use semget() to get a semaphore set but I keep getting an EEXIST error, even after I make a new key尝试使用 semget() 获取信号量集,但我不断收到 EEXIST 错误,即使在我创建了新密钥之后也是如此
【发布时间】:2023-03-25 01:36:01
【问题描述】:

所以我目前正在编写一个服务器/客户端程序,它将接收三个命令(HI、PID 和 GOODBYE)并相应地处理它们。我在 server.c 代码中使用 semget() 似乎遇到了一些麻烦。

我得到的错误是“EEXIST”,根据手册页,它说密钥已经存在(duh lol) - 问题是,我每次都手动更改密钥,它仍然给我错误。我不明白这里的东西吗?它似乎也适用于 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 );
}

【问题讨论】:

  • 那么这里的问题是什么?这不是最小的吗?我觉得删除任何东西都可能难以发现问题?我想我可以取出client.c,因为服务器问题最多?只是链接该页面对我没有任何帮助。 @PasserBy
  • 您可能想重新阅读 shmctl() 上的手册页并阅读 shmdt() 上的手册页
  • 对于初学者,您有一个标记为永远无法到达的循环。这与您的问题无关。尝试将问题提炼到完全复制您的问题所需的绝对最小值。

标签: c linux server client ipc


【解决方案1】:

您需要使用 ftok 函数制作一个 system V IPC 密钥。然后,该键应作为第一个参数传递给 shmget 系统调用。这同样适用于信号量。使用 ftok 创建一个 System V IPC 密钥并将其作为第一个参数传递给 semget。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-23
    • 2020-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    相关资源
    最近更新 更多