shmat()为同一个“shmkey”返回一个不同的“shmaddr”

时间:2011-12-08 17:21:50

标签: c posix shared-memory producer-consumer

这是我的设置......

/* 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?

提前致谢,

ž@ķ!

3 个答案:

答案 0 :(得分:5)

涉及两组地址。 “芯片RAM地址”,也就是硬件,物理,实际或超级用户地址,从第一个RAM芯片开始,为0并向上移动。但是,在所有“真正的多任务”操作系统中,每个进程都有自己的“虚拟内存”。 CPU和操作系统协作为每个进程提供单独在自己的机器上的“错觉”,具有自己的地址空间,具有从“虚拟”映射的表(在内核和CPU中,取决于体系结构)(每个进程) -process)地址为“real / hardware / supervisor”地址。

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

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

答案 1 :(得分:3)

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

答案 2 :(得分:2)

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

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