2016-09-26 2 views
0

Это я ожидал два файла для обмена памятью, один из них записывает данные для обмена памятью, другой - данные из общей памяти и данных printf ; но есть что-то заблуждение.Ошибка памяти: shmat return NULL, errno (22: Недопустимый аргумент) в CentOS6.8

shm_w.c

#include <stdio.h> 

#include <sys/shm.h> 

#include <string.h> 

#define MAX_MEM 4096 




int main() 
{ 

    int shmid; 
    int ret; 
    void* mem; 

    shmid=shmget(0x12367,MAX_MEM,IPC_CREAT | 0666); 
    printf("shmid is = %d,pid=%d\n",shmid,getpid()); 
    mem=shmat(shmid,(const void*)0,0); 
    if((int)mem==-1) 
    { 
      printf("attach faile.\n"); 
    } 

    strcpy((char*)mem,"Hello,this is test memory.\n"); 

    ret=shmdt(mem); 

return 0; 

} 

shm_r.c

#include <errno.h> 

#include <stdio.h> 

#include <sys/shm.h> 

#include <string.h> 

#define MAX_MEM 4096 



int main() 

{ 

     int shmid; 
     int ret; 
     void* mem; 

     shmid=shmget(0x12367,MAX_MEM,0); 
     mem=shmat(shmid,(const void*)0,0); 
     //printf("%s\n",(char*)mem); 
     if(mem==(void*)-1) 
     { 
      fprintf(stderr,"shmat return NULL ,errno(%d:%s)\n",errno,strerror(errno)); 
      return 2; 
     } 
     printf("%s\n",(char*)mem); 

     shmdt(mem); 

return 0; 



} 

Когда я в CentOS6.8 компиляции двух .c файлов, в первый раз, это нормально.

К сожалению, с этого момента, я Рунический she_w.c был прав тоже:

Шмид является = 65537, PID = 7116.

, но когда я бегу shm_r.c, это появляется ошибка:


shmat return NULL ,errno(22:Invalid argument)


, так что я не знаю, что случилось это? Я пытаюсь его решить, например, использовал ipcs -m, но не отображал shmid. И я кошка/proc/7116/maps: «Нет такого файла или каталога»

кто может сказать мне, что произойдет? И как я могу найти Шмид в CentOS6.6

uname -r: 
2.6.32-504.12.2.el6.x86_64 

Я также использую кошку/ргос/sysvipc/ГИМ | grep 65537, но не появляется shmid. Не повезло!

Скажите, пожалуйста, как решить проблему, если вы знаете, спасибо!

+0

'(сопзЬ пустота *) 0 '- используйте' NULL' макрос, чтобы получить _null указатель constant_. – Olaf

+1

Вы управляете этими двумя программами один за другим? Как вы думаете, что произойдет, когда первая программа отделит сегмент памяти до запуска другой программы? Вам нужно дождаться запуска другой программы, прежде чем вы сможете отсоединить сегмент. –

+0

«Вы запускаете эти две программы один за другим? Как вы думаете, что произойдет, когда первая программа отделит сегмент памяти до запуска другой программы? Вам нужно дождаться запуска другой программы, прежде чем вы сможете отсоединить сегмент. " Почему необходимо отключить после чтения программу и не может отсоединиться при записи программы? Я имею в виду, что запись данных записи записи завершена, она может отсоединиться, я не знаю, почему, когда запись программы завершена, можно использовать отсоединение. если я использовал отсоединенный в программе записи, общий объем памяти будет свободен, поэтому программа чтения не сможет читать данные? – Marcos

ответ

0

Я загрузил и запустил вашу программу и не смог воспроизвести ваши [противоречивые] результаты.

Чтобы отобразить активные сегменты shm, используйте команду ipcs. Если вам нужно удалить созданную вами, вы можете использовать команду ipcrm.

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

Разрешения на сегмент, потому что вы создали его неправильно в первый раз. ipcs должен показать это.

Когда вы отлаживали свою программу для писателя, возможно, что-то неправильно. Это можно увидеть с помощью ipcs. Если ошибка была сделана, вы можете вручную удалить сегмент с помощью ipcrm и повторить попытку своей программы.

Другая возможность заключается в том, что ваш ключ сталкивается с другим сегментом, созданным другой программой. Это маловероятно по двум причинам.

Ваш ключ, по всей видимости, уникален. Это также можно проверить с помощью ipcs

В большинстве программ в настоящее время используется ключ 0x00000000, который является «частным» режимом.Это делается, когда программа выполняет fork, но делает не делает execvp. Ребенок просто вызывает некоторую функцию (например, child_worker). Родитель и ребенок передают данные взад и вперед, используя «частный» сегмент. Поскольку сегмент является частным, вам не нужно беспокоиться о наличии уникального значения ключа.

Поскольку у вас есть две отдельные программы, использование этого режима будет не работать для вашего использования. Вам нужно значение ненулевого ключа, поэтому ваш сегмент будет persist от одного вызова программы к следующему.


Для простоты я объединил обе программы в одну. Я также добавил вариант удаления сегмента shm.

Примечание: Я сделал косметическую очистку только. Я сделал не исправить любые ошибки. Таким образом, это просто FYI за то, что я испытал на моей системе:

#include <stdio.h> 
#include <sys/shm.h> 
#include <string.h> 
#include <errno.h> 
#include <stdlib.h> 
#include <unistd.h> 

#define MAX_MEM 4096 
#define XID  0x12367 

int opt_cmd; 

void 
writer(void) 
{ 
    int shmid; 
    void *mem; 

    shmid = shmget(XID,MAX_MEM,IPC_CREAT | 0666); 
    printf("shmid is = %d,pid=%d\n",shmid,getpid()); 
    mem = shmat(shmid,NULL,0); 
    if (mem == (void *) -1) { 
     printf("attach faile.\n"); 
    } 

    strcpy((char *) mem,"Hello,this is test memory.\n"); 

    shmdt(mem); 
} 

void 
reader(void) 
{ 
    int shmid; 
    void *mem; 

    shmid = shmget(XID,MAX_MEM,0); 
    mem = shmat(shmid,NULL,0); 

    // printf("%s\n",(char*)mem); 
    if (mem == (void *) -1) { 
     fprintf(stderr,"shmat return NULL ,errno(%d:%s)\n", 
      errno,strerror(errno)); 
     exit(2); 
    } 

    printf("%s\n",(char *) mem); 

    shmdt(mem); 
} 

void 
clean(void) 
{ 
    int shmid; 

    shmid = shmget(XID,MAX_MEM,0); 
    shmctl(shmid,IPC_RMID,NULL); 
} 

// main -- main program 
int 
main(int argc,char **argv) 
{ 
    char *cp; 

    --argc; 
    ++argv; 

    for (; argc > 0; --argc, ++argv) { 
     cp = *argv; 
     if (*cp != '-') 
      break; 

     switch (cp[1]) { 
     case 'd': 
     case 'w': 
     case 'r': 
      opt_cmd = cp[1]; 
      break; 

     default: 
      break; 
     } 
    } 

    switch (opt_cmd) { 
    case 'w': 
     writer(); 
     break; 

    case 'd': 
     clean(); 
     break; 

    default: 
     reader(); 
     break; 
    } 

    return 0; 
} 
0

Для использования вызова shmget(), необходимо включить <sys/ipc.h>.

shm_w.c

#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <sys/ipc.h> 
#include <sys/shm.h> 
#include <string.h> 

#define MAX_MEM 4096 

int main() 
{ 

    int shmid; 
    int ret; 
    void* mem; 

    shmid=shmget(0x12367,MAX_MEM,IPC_CREAT | 0666); 
    printf("shmid is = %d,pid=%d\n",shmid,getpid()); 
    mem=shmat(shmid,(const void*)0,0); 
    if(mem==(void *) -1) 
    { 
      printf("attach faile.\n"); 
    } 

    strcpy((char*)mem,"Hello,this is test memory.\n"); 

    ret=shmdt(mem); 

    return 0; 

} 

shm_r.c

#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <sys/ipc.h> 
#include <sys/shm.h> 
#include <string.h> 
#include <errno.h> 

#define MAX_MEM 4096 

int main() 

{ 

     int shmid; 
     int ret; 
     void* mem; 

     shmid=shmget(0x12367,MAX_MEM,0); 
     mem=shmat(shmid,(const void*)0,0); 
     //printf("%s\n",(char*)mem); 
     if(mem==(void *) -1) 
     { 
      fprintf(stderr,"shmat return NULL ,errno(%d:%s)\n",errno,strerror(errno)); 
      return 2; 
     } 
     printf("%s\n",(char*)mem); 

      shmdt(mem); 

    return 0; 
    } 

    $ gcc shm_w.c -o shm_w 
    $ gcc shm_r.c -o shm_r 
    $ ./shm_w 
    shmid is = 2293774,pid=5779 
    $ ./shm_r 
    Hello,this is test memory. 

    $ ./shm_r 
    Hello,this is test memory. 

    $ ./shm_r 
    Hello,this is test memory. 
Смежные вопросы