2016-11-08 8 views
0

공유 메모리 세그먼트를 통해 두 프로세스간에 통신하기를 원하는 코드가 있습니다. 내 문제는 내가 메모리 세그먼트를 연결하는 오류가 걸릴 이유를 모르겠다.공유 메모리 세그먼트를 연결할 때 오류가 발생했습니다.

#include <stdio.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <stdlib.h> 
#include "process.h" 

int main(int argc, char** argv) 
{ 
    /*- Check the command-line arguments -*/ 
    if(argc != 2) 
    { 
     printf("\n--- Wrong input at command-line arguments ---\n\n"); 
     printf("--- The program terminate --- \n"); 
     return 1; 
    } 

    int N = atoi(argv[1]);  // The amount of total threads to be created 
    int status;   // for the wait() function 
    char* data;   // a string to use for shared memory segment 

    /*- Variables for the shared memory segment -*/ 
    key_t key = 1003;  // for the shmget() key argument 
    int shmid;   // to store the returned value from shmget() 
    int size = 1024;  // for the shmget() size argument 


/* ************************************************************************************/ 

    pid_t pid = fork(); // create second process 

    if(pid < 0)  // if something going wrong 
    { 
     printf("\n\n---- Error in function fork!----\n"); 
     exit(1); 
    } 
    else if(pid == 0) // the child process (P) 
    { 
     // create the shared memory segment for the P process 
     shmid = CreateShmSegment(key, size, IPC_CREAT); 

     if(shmid == -1)  // check if creating shared memory return an error 
     { 
      printf("\n---Error at creating the memory segment! ---\n"); 
      exit(1); 
     } 

     // attach the shared memory segment 
     data = AttachShmSegment(shmid); 

     if(data == (char*)-1) // check if attached the shared memory return an error 
     { 
      printf("\n---Error at attaching the memory segment! ---\n"); 
      exit(1); 
     } 

     char* str = data; 
     sprintf(str, "testing"); 

//  ChildProcess(); 
     printf("\n** Child process! ** \n"); 
     printf("N = %d\n", N); 
     printf("write: %s\n",str); 

     // detach the shared memory segment 
     if(shmdt(data) == -1)  //check for error 
     { 
      printf("\n---Error at detaching memory segment! ---\n"); 
      exit(1); 
     } 
    } 
    else   // the parent process (C) 
    { 
     // create the shared memory segment for the C process 
     shmid = CreateShmSegment(key, size, IPC_CREAT); 

     if(shmid == -1)  // check if creating shared memory return an error 
     { 
      printf("\n---Error at creating the memory segment! ---\n"); 
      exit(1); 
     } 

     // attach the shared memory segment 
     data = AttachShmSegment(shmid); 
     if(data == (char*)-1) // check if attached the shared memory return an error 
     { 
      printf("\n---Error at attaching the memory segment! ---\n"); 
      exit(1); 
     } 

//  ParentProcess(); 
     wait(&status); 
     printf("\n** Parent process! **\n"); 
     printf("N = %d\n",N); 
     printf("read from segment: %s\n", data); 

     // detach the shared memory segment 
     if(shmdt(data) == -1)  //check for error 
     { 
      printf("\n---Error at detaching memory segment! ---\n"); 
      exit(1); 
     } 

     // deallocate the shared memory segment 
     if(DeallocateShmSegment(shmid) == -1) //check for error 
     { 
      printf("\n---Error at destroy memory segment! ---\n"); 
      exit(1); 
     } 
    } 

    return 0; 
} 

견적과 다른 두 개의 파일을 컴파일합니다.

process.h :

#ifndef __Processes_H_ 
#define __Processes_H_ 
#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/shm.h> 
#include <stdio.h> 

void ChildProcess(); 
void ParentProcess(); 
int CreateShmSegment(key_t, size_t, int); 
void* AttachShmSegment(int); 
int DetachShmSegment(const void*); 
int  DeallocateShmSegment(int); 

#endif 

그리고 위해 'process.c :

#include "process.h" 

void ChildProcess() 
{ 

} 


/***************************************************************/ 

void ParentProcess() 
{ 

} 

/****************************************************************/ 

int CreateShmSegment(key_t key, size_t size, int flag) 
{ 
    int id; 
    id = shmget(key, size, flag); 
    return id; 
} 

/*****************************************************************/ 

void* AttachShmSegment(int id) 
{ 
    char* data = NULL; 
    data = (char*) shmat(id, NULL, 0); 
    return data; 
} 

/*****************************************************************/ 

int DetachShmSegment(const void* addr) 
{ 
    return shmdt(addr); 
} 

/*****************************************************************/ 

int DeallocateShmSegment(int id) 
{ 
    return shmctl(id, IPC_RMID, NULL); 
} 

내가 메모리를 장착 잘못 무슨 일이 일어나고 있는지 모른다. 나는 웹을 검색하고 shmat() 인수에 약간의 변경을가했지만 해결할 수 없었다.

+3

오류가 발생하지만 어떤 오류가 발생합니까? ['errno'] (http://man7.org/linux/man-pages/man3/errno.3.html)를 확인 했습니까? 예를 들어 사용 해본 적이 있습니까? ['strerror'] (http://man7.org/linux/man-pages/man3/strerror.3.html)에 오류의 인쇄 가능한 문자열이 있습니까? –

+1

System V 기능을 반드시 사용해야합니까? 그렇지 않으면'mmap'은 공유 메모리를 관리하는 "현대적인"방법입니다. [이 SO post] (http://stackoverflow.com/questions/21311080/linux-shared-memory-shmget-vs-mmap) – LPs

+0

일반적으로 파일에 어떤 것도 포함시키지 마십시오. 해당 파일 내에서 사용되지 않습니다. I.E. Process.h 파일의 헤더 파일에는 해당 내용이 사용되지 않습니다. 실제로 필요할 때 헤더 파일을 포함 시키십시오. – user3629249

답변

0

여기에서 문제는 두 프로세스 모두에서 shmid를 얻으려는 것이고 두 프로세스 모두 CreateShmSegment()를 호출 할 때 서로 다른 shmid를 가져와 실패한 것입니다.

fork() 전에 CreateShmSegment() 및 AttachShmSegment()를 호출하십시오.

+0

분기를 만들기 전에 세그먼트를 생성하고 연결하는 것은 좋은 생각이지만 그렇게하지 않으면 책임을지지 않을 것입니다 오류. 부모와 자식이 공유 메모리 세그먼트에 대해 서로 다른 ID를 가질 수 있다는 것은 중요하지 않습니다. 이러한 ID는 순전히 각 프로세스에 국한됩니다. 글로벌 세그먼트 식별자로 사용되는 지정된 세그먼트 * 키 *입니다. –

+0

@JohnBollinger 당신의 키가 같지 않으면 어떻게 공유 세그먼트를 얻을 수 있습니까? 여기에서 나는 shmget에서 전달한 키가 두 프로세스에서 동일해야 함을 의미합니다. –

+0

OP *는 shmget()에 대한 두 호출에서 같은 키를 전달합니다. 어쨌든, 그것은 부모와 자식이'shmget()'/'CreateShmSegment()'(같은 키에 대해)에서 다른'shmid' 값을받는 것이 문제가 될 것이라는 당신의 답과는 아무런 관련이 없습니다. . 그 단언은 단순히 틀리다. –

1

세그먼트를 만들 때 모드 플래그를 지정하지 않습니다. 따라서 작성자를 포함하여 누구나 읽기 또는 쓰기 액세스를 사용하지 않고 생성 될 것으로 기대합니다. 이는 그 자체로 오류가 아니지만, 특권이없는 프로세스가 해당 모드가있는 동안 해당 세그먼트를 연결하려는 모든 시도는 EACCES으로 실패합니다.

세그먼트를 만들 때 플래그에 적어도 S_IRWXU을 포함 시키거나 세그먼트의 모드를 수정하여 소유자에 대한 읽기 및 쓰기 권한을 허용 한 후에 shmctl()을 사용하는 것이 좋습니다. (이 S_IRUSR | S_IWUSR를 사용하는 동등한 것 때문에 실행 권한을 참고,이 목적을 위해 의미가 없습니다.) 예를 들어,

shmid = CreateShmSegment(key, size, IPC_CREAT | S_IRWXU); 

은 아마도 당신은 광범위한 액세스 권한을 부여 할.

처음에는 fork 한 다음 부모 및 자식 프로세스 모두에서 공유 메모리 세그먼트를 만들고 첨부하는 것이 이상하다는 점에 유의하십시오. 첨부 된 공유 메모리 세그먼트는 fork()에 상속되므로, 을 생성하고 첨부하려면보다 깨끗해야합니다 ().

+0

나는 포크를 시험해 보았다. 내가받을 오류는 '-1'을 반환하는 첨부 함수 호출 후입니다. – aragon

+0

@aragon, 내 대답 전체를 읽었습니까? 포크 뒤에있는'shmget()'과'shmat()'의 위치는 차선이지만 실제 문제는 아닙니다. 어쨌든, 그 함수들 중 하나가 -1을 반환함으로써 에러를 표시 할 때, 더 많은 정보를 얻기위한 일반적인 메커니즘은'errno'를 직접 참조하거나'perder()'를 즉시 호출하여 적절한 에러 메시지를'stderr '. 도넛에 돈을 걸면 내가 설명한 것과 같은 액세스 제어 문제가 드러납니다. –

0

라인의 종류 :에

shmid = CreateShmSegment(key, size, IPC_CREAT); 

가 정확하지, 그것과 비슷해야합니다

shmid = CreateShmSegment(key, size, IPC_CREAT|0666); 

모든 사람에게 (이 경우) 읽기/쓰기 권한을 부여

일단 공유 메모리 세그먼트가 생성되면 (적절한 권한을 사용하지 않으면) 사용자는 공유 메모리를 파괴해야합니다. 결과 목록에서

ipcs -m 

,

dest 가진 사람들은 더 이상 사용되지 않는 파괴해야한다 : 공유 메모리 사용을 나열합니다.

권한 열에 0이있는 항목도 삭제해야합니다. 문제 후 목록 코드의

출력에서 ​​가져온 32768 공유 메모리 ID입니다

ipcrm shm 32768 

은, 코드를 수정하고 '나쁜'공유 :

당신은을 통해 공유 메모리를 파괴 할 수있다 메모리가 손상됨 :

** Child process! ** 
N = 2 
write: testing 

** Parent process! ** 
N = 2 
read from segment: testing 
관련 문제