2009-04-12 4 views
4

동일한 파일을 매핑하는 메모리를 사용하여 서로 다른 두 프로세스가 통신하도록 허용하려고합니다. 그러나, 나는 이것에 약간의 문제가있다. 이것은 open() 호출을 사용하고 mmap에 파일 기술자를 전달하는 것과 관련이 있다고 생각합니다.파일 위로 mmap 사용

여기 내 코드는 무엇입니까?

개체 1의 코드 :

16  FILE* temp = fopen(theSharedFileName, "w"); 
17  fseek(temp, fileSize-1, SEEK_SET); 
18  fprintf(temp, "0"); // make the file a certain size 
19  fseek(temp, 0, SEEK_CUR); 
20 
21  int sharedFileName = fileno(temp); 
... 
31  sharedArea = (MyStruct*)mmap(0, fileSize, 
32   PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, sharedFileName, 0); 

나는 개체 1은 오직 한 번 할 것이기 때문 "w"파일 모드를 사용하고 나는 그것이 이전에 기존 데이터를 재설정 할 수 있습니다.

개체 2의 코드 :

130  FILE* tempFile = fopen(sharedFileName, "a"); 
131  int theFile = fileno(tempFile); 
... 
135  sharedArea = (MyStruct*)mmap(NULL, fileSize, 
136   PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, theFile, 0); 
+0

직면 한 정확한 문제는 무엇입니까? obj2가 obj1보다 먼저 파일에 액세스하지 않도록 할 수 있습니까? – dirkgently

+0

예, obj1은 더 많은 서버이고 obj2는 나중에 시작될 클라이언트와 같습니다. – samoz

답변

24

몇 가지 문제 : mmap에 같은

  1. 피가 높은 수준을 혼합 I/O (는 fopen(), fseek는()) 및 일부 낮은 수준의 작업(). fileno()를 사용하여 하위 수준의 파일 설명자를 가져올 수도 있지만 가장 긴 경로를 사용하여 같은 위치에 도달하는 것과 같습니다. 또한 mmap()을 사용하면 BSD와 POSIX를 뛰어 넘는 호환성을 잃어 버리기 때문에 표준 C 입출력 함수를 사용하지 않아도됩니다. 그냥 open()과 lseek()를 직접 사용하십시오.
  2. 메모리 매핑과 동일한 파일에서 스트림 형식의 I/O (fprintf())를 사용하는 것은 이치에 맞지 않습니다. 파일을 메모리 맵핑 할 때 시스템에 임의 액세스 (직접 인덱싱) 데이터로 사용할 것을 암시 적으로 알려줍니다. fprintf()는 스트림 출력을위한 것이며 보통 순차 액세스에 사용합니다. 사실, 가능한 한 fprintf()와 fseek()가 같은 디스크립터 (이것은 휴대용이 아니지만 이전 항목 때문에 이동성을 고려하지 않음)에서 볼 수 있습니다.
  3. 보호는 열린 파일 보호와 일치해야합니다. fopen()에 "w"를 전달하고 mmap()에 PROT_READ | PROT_WRITE | PROT_EXEC을 전달 했으므로이 제한을 위반하는 것입니다. 이것은 또한 높은 수준의 I/O와 메모리 매핑을 섞어서는 안되는 이유를 강조합니다. fopen(...,"w")이 올바른 플래그로 파일을 열 것이라고 어떻게 보장합니까? 이것은 C 라이브러리의 "구현 세부 사항"이라고 가정합니다. 읽기 및 쓰기 권한으로 파일을 메모리 맵핑하려면 저수준 open(theSharedFileName, O_RDWR)을 사용하여 파일을 열어야합니다.
  4. PROT_WRITEPROT_EXEC을 함께 사용하지 마십시오. 은 이식 할 수 없으므로 보안 위험이 있습니다. W^Xexecutable space protection에 대해 읽어보십시오.
+0

아주 완전한 대답입니다. – Anthony

+1

일부 답변은 잘못된 정보로 보입니다. 나는'fprintf'와'fseek'가 함께 사용할 수 없다고 왜 혼란스러워합니다. 그리고 # 3과 파일 모드와 마찬가지로 POSIX는 'fopen'모드 문자열이 파일 디스크립터 모드로 변환하는 방법을 매우 명시 적으로 지정합니다. 구현 관련 사항이 아닙니다. –

1

다른 사람들처럼 fopen() 및 친구를 사용하지 마십시오.

fprintf()가 스트림 버퍼를 가질 수 있기 때문에 실제로 문제가 발생하지 않을 수 있습니다. 따라서 실제로 파일을 변경하지 않아서 예상 한대로 다른 프로세스에서 볼 수 있습니다. fflush()를 추가 할 수는 있지만 read() 및 write()는 응용 프로그램 수준 버퍼링을 수행하지 않습니다. 이는 더 적합한 이유의 일부입니다.

2

C++을 사용할 수 있고 ACE 또는 Boost과 같은 라이브러리는 낮은 수준의 세부 정보를 차단하고 IPC에 대한 더 쉬운 추상화를 제공합니다.