shmat() возвращает другой shmaddr для того же shmkey

Вот моя установка...

/* 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: (разветвит() процессы «Производитель» и «Потребитель»)

/* 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 получают разные shmaddr при подключении, когда у них один и тот же shmid?

Заранее спасибо,

Z@K!


person Zak    schedule 08.12.2011    source источник


Ответы (3)


Здесь задействовано два набора адресов. «Адреса чипа RAM», также известные как аппаратные, физические, реальные адреса или адреса администратора, начинаются с вашего первого чипа RAM с 0 и двигаются вверх. Однако во всех «настоящих многозадачных» операционных системах каждый процесс получает собственную «виртуальную память». ЦП и ОС совместно создают каждому процессу «иллюзию», что он один на своей машине, со своим адресным пространством, с таблицей (в ядре и ЦП, в зависимости от архитектуры), отображаемой из «виртуального» (по -process) обращается к адресам "real/hardware/supervisor".

Общая память — это особый случай, когда одна и та же «реальная память» адресуется более чем одним процессом. Виртуальные адреса, которые возвращает "shmat", являются локальными для каждого вызывающего абонента.

Аналогичным образом, когда вы загружаете библиотеку общих объектов (.so), она может отображаться в разных адресных пространствах в каждом процессе.

person BRPocock    schedule 08.12.2011
comment
У меня была ошибка в Потребителе, и я использовал несовпадающие адреса как козла отпущения. Он работает отлично, как вы и сказали. С другой стороны, я многое узнал о shmget() и shmat()! ;-) - person Zak; 08.12.2011

Вполне допустимо, что один и тот же сегмент общей памяти отображается на разные виртуальные адреса в разных процессах.

person Nikolai Fetissov    schedule 08.12.2011

когда процесс вызывает shmat(), он возвращает виртуальный адрес разделяемой памяти. виртуальный адрес — это место в памяти, которое видит текущий процесс. другой процесс может отображать общую память на другой виртуальный адрес в адресном пространстве процесса и, следовательно, разные возвращаемые значения вызова shmat() для разных процессов.

хорошее графическое описание того, что я только что сказал выше. http://poshmodule.sourceforge.net/posh/html/node3.html

person sunil    schedule 12.07.2012