【问题标题】:shmat() is returning a different "shmaddr" for same "shmkey"shmat() 为相同的“shmkey”返回不同的“shmaddr”
【发布时间】:2026-01-07 18:55:02
【问题描述】:

这是我的设置...

/* Bounded Buffer item structure */
struct item {
    int  id;  /* string index value */
    char str[80];  /* string value */
};

/* Structure for the shared memory region */
typedef struct {
    int    debug;           /* debug flag */
    int    in;              /* index of next empty slot */    
    int    out;             /* index of next full slot  */
    char   MUTEXname[32];   /* name of the MUTEX semaphore */
    char   EMPTYname[32];   /* name of the EMPTY semaphore */
    char   FULLname[32];    /* name of the FULL semaphore  */
    struct item buff[BUFFSIZE];  /* circular buffer for producer/consumer items*/
    char   strarray[MAX_STRINGS][80]; /* shared array of strings for consumers */
} shr_mem_t;

/* Values for obtaining a shmid key via ftok() */
#define KEYPATH "."
#define KEYPROJ 4520

Main:(将 fork() “Producer”和“Consumer”进程)

/* Use ftok() to get a value for a key to identify a shared memory segment */
shm_key = ftok(KEYPATH, KEYPROJ);

/* Create the shared memory segment */
shmid = shmget(shm_key, sizeof(shr_mem_t), IPC_CREAT | IPC_EXCL | 0660);

/* Attach shared memory segment to the parent process */
shmptr = shmat(shmid, NULL, 0);

制作人:

/* Use ftok() to get value for the key to identify the shared memory segment */
shm_key = ftok(KEYPATH, KEYPROJ);

/* Get the ID of the existing shared memory segment */
shmid = shmget(shm_key, sizeof(shr_mem_t), 0660);

/* Attach the shared memory segment */
shmptr = shmat(shmid, NULL, 0);

消费者:

/* Use ftok() to get value for the key to identify the shared memory segment */
shm_key = ftok(KEYPATH, KEYPROJ);

/* Get the ID of the existing shared memory segment */
shmid = shmget(shm_key, sizeof(shr_mem_t), 0660);   

/* Attach the shared memory segment */
shmptr = shmat(shmid, NULL, 0);

错误测试:(为简洁起见...)

if (shmid == -1) {
    perror("shmget failed in __________");
    exit(1);
} else {
    sprintf(errString, "<*> __________ shared memory id: %i ", shmid);
    perror(errString);
}

if(shmptr == (void *)(-1)) {
    perror("shmat failed in __________");
    exit(1);
} else {
    sprintf(errString, "<*> __________ attaching to shared memory address: %p ", shmptr);
    perror(errString);
}

输出:

<*> Main creating shared memory id: 101376 : No such file or directory
<*> Main attaching to shared memory address: 16000 : No such file or directory
Creating the producer and consumer processes...
<*> Producer located shared memory id: 101376 : Successful
<*> Consumer located shared memory id: 101376 : Successful
<*> Producer attaching to shared memory address: 10000 : Successful
<*> Consumer attaching to shared memory address: 10000 : Successful

共享内存地址是怎么回事? Main 和 Prod/Cons 进程在具有相同 shmid 时附加时如何获得不同的 shmaddr?

提前致谢,

Z@K!

【问题讨论】:

    标签: c posix shared-memory producer-consumer


    【解决方案1】:

    涉及两组地址。 “芯片 RAM 地址”,即硬件、物理地址、真实地址或主管地址,从您的第一个 RAM 芯片 0 开始并向上移动。然而,在所有“真正的多任务”操作系统上,每个进程都有自己的“虚拟内存”。 CPU 和 OS 协作给每个进程一个“幻觉”,即它在自己的机器上独处,有自己的地址空间,有一个表(在内核和 CPU 中,取决于架构)从“虚拟”(每个-process) 地址到“真实/硬件/主管”地址。

    共享内存是一种特殊情况,其中相同的“真实内存”由多个进程寻址。 “shmat”返回的虚拟地址对于每个调用者都是本地的。

    同样,当您加载共享对象 (.so) 库时,它可能会在每个进程中映射到不同的地址空间。

    【讨论】:

    • 我在消费者中有一个错误,我将不匹配的地址用作替罪羊。正如你所说,它工作得很好。从好的方面来说,我学到了很多关于 shmget() 和 shmat() 的知识! ;-)
    【解决方案2】:

    同一共享内存段在不同进程中映射到不同的虚拟地址是完全合法的。

    【讨论】:

      【解决方案3】:

      当进程调用 shmat() 时,它会返回共享内存的虚拟地址。 虚拟地址是当前进程看到的内存位置。 不同的进程可以将共享内存映射到不同的虚拟地址 在进程地址空间中,因此 shmat() 调用的不同返回值 针对不同的工艺。

      对我上面所说的内容进行了很好的图片描述。 http://poshmodule.sourceforge.net/posh/html/node3.html

      【讨论】:

        最近更新 更多