2016-12-26 2 views
1

의 내가 구조의 (고정 된 길이 N의) C 배열을 저장할 가정 해 봅시다 .리눅스에서 매핑 된 파일에 저장된 구조 데이터를 관리 할 수있는 이식 가능한 방법이 있습니까? 프로그램이 파일에서 배열을 읽을 수 있도록, 파일에</p> <pre><code>typedef struct { type0 field0; type1 field1; } foo_struct; foo_struct array[N]; </code></pre> <p>그것을 조작하고, 다시 쓰기 :

typen의 각 인스턴스를 쓰려면 프로그램에서 write 시스템 호출을 사용할 수 있습니다. 그런 다음 프로그램을 호출 할 때 sizeof(typen)이 이전과 같다고 가정하면 메모리에 배열을 할당하고 read을 사용하여 필드 채우기를 수행 할 수 있습니다. 나는 이식성 문제로 인해 한 번에 전체 구조를 안정적으로 채울 수있는 방법이 없다고 생각합니다. 잘못된 것이라면 저를 교정하십시오.

하지만 내 목적에는 너무 느립니다. 한 번에 모든 것을 큰 버퍼로 읽더라도 필드로 복사해야합니다. 내 데이터 크기가 "yuuge"이지만 조작은 산발적입니다. 읽기 및 복사는 실제 데이터 액세스보다 더 많은 시간이 걸립니다.

따라서 mmap을 사용하는 것이 더 좋으며 mmap은 주문형으로 작동한다고 가정하고 있습니다. 틀렸을 경우에도 다시 알려주십시오.

이제 더 빨라질 수 있지만 메모리의 데이터에 액세스하는 데 문제가 있습니다.

mmap에서 반환 값을 지정하면 함수가 버퍼를 반환합니다.이 버퍼는 정렬되지 않을 수도 있으며, sizeof(foo_struct)의 배수로 정렬 되었더라도 이식 가능하게 보장되지는 않습니다 struct 및 -> 연산자에 대한 포인터가있는 필드에 액세스 할 수 있습니다.

그래서 나는 모든 구조를 식별 잊고, 그냥 크기 S0 = sizeof(field0)S1 = sizeof(field1)S = S0 + S1의 덩어리의 시리즈로 내 배열을 생각하고, 데이터 포인터 연산을 사용함으로써, 손으로 계산해야 생각 : 내가 읽거나 fieldn을 쓰고 싶다면

다음
buffer + M * S 
buffer + M * S + S0 

가, 심지어 포인터, 정렬되지 않은, 나는 천천히 인 바이트에 데이터를 분할해야하고 바이트 단위로 해. 이렇게 많은 액세스가 없지만이 전체 프로세스를 반복하는 경우가 많기 때문에 최대한 빨리 처리해야합니다.

mmap (또는 다른 방식으로 전체 yuuge 파일을 읽을 필요가 없습니다)을 사용할 수 있습니까? 그렇지만 데이터를 필드 바이 필드 및 바이트 단위로 액세스 할 필요가 없습니까?

필자가 쓴 것 중 일부가 Linux 나 일반적인 품위에 어긋나는 경우 공유하십시오. 그렇지 않다고 확신하지는 않습니다.그냥 데모 용으로

+1

1) mmap()은 * 정렬 된 * 포인터를 반환하며 모든 유형에 적합합니다. 2) 그러나 그것은 내 목적에 비해 너무 느리다. "당신은 그것을 측정 했습니까? 방법? – wildplasser

+0

음 ... 이것은 SSCCE입니다. 실제 상황은 구조가 거대 할 수 있다는 것입니다. 따라서 크기가 K 여야 할 수도 있습니다. 따라서 페이지를 정렬한다고 가정하고 싶지는 않습니다. 괜찮습니다. OK, 심지어 페이지 크기가 구조체 크기의 2의 다음 제곱보다 작다고 가정해도 페이지 정렬 포인터가 적합할까요? 당신은 이식 가능하게 말해서 포인터가 구조체 크기에 의해 "나눌 수있는"경우 구조체에 대한 정렬 정렬과 같은 것이 없다는 것을 알고 있습니까? –

+0

나는 측정하지 않았다. 나는 파일의 크기가 엄청나게 클 수 있다는 것을 알고 있으며, 그렇지 않다는 것에 의존하기를 원하지 않으며, 많은 반복이 있습니다. 내 말은, 그 디스크에 디스크가 있고, 네가 거기에 회전하는 디스크가 여전히 많다는 것이다. 나는 그것이 모두 플래시라고 가정 할 수 없다. 그리고 회전한다면 너무 느리다. 내가 쓴 것처럼 너무 느리다 고 가정하십시오. –

답변

0

, 이진 파일에서 표준 읽기 구조체 배열 :

#include <stdio.h> 
#include <unistd.h> 
#include <fcntl.h> 

struct omg{ 
     int num; 
     char buff[122]; 
     double values[23]; 
     }; 

#define NNN (3*1024*1024) 
#define FILENAME "omg.dat" 
#define COUNTOF(a) (sizeof a/sizeof a[0]) 

struct omg array[NNN]; 

int main(void) 
{ 
int fd; 
int ret, ii, jj; 

fprintf(stderr, "Sizeof array[0] is %zu\n", sizeof array[0]); 
     /* initialise the array to nonsence */ 
for (ii=0; ii < COUNTOF(array); ii++) { 
     array[ii].num=ii; 
     sprintf(array[ii].buff, "Hello world %d", ii); 
     for (jj=0; jj < COUNTOF(array[0].values); jj++) { 
       array[ii].values[jj] = ii/(jj+1) ; 
       } 
     } 

fd = open(FILENAME, O_RDWR|O_CREAT, 0660); 
if (fd < 0) return 1; 

ret = read(fd, array, sizeof array); 
fprintf(stderr, "Read %d/ %zu\n", ret, sizeof array); 

     /* modify the nonsence */ 
for (ii=0; ii < COUNTOF(array); ii++) { 
     array[ii].num += 1; 
     sprintf(array[ii].buff, "Hello world %d", array[ii].num); 
     for (jj=0; jj < COUNTOF(array[0].values); jj++) { 
       array[ii].values[jj] = array[ii].num/(jj+1) ; 
       } 
     } 

ret = lseek(fd, 0, SEEK_SET); 
fprintf(stderr, "Seek = %d\n", ret); 


ret = write(fd, array, sizeof array); 
fprintf(stderr, "Wrote %d/ %zu\n", ret, sizeof array); 

close(fd); 
return 0; 
} 

결과 :

[email protected]$ vi readstruct.c 
[email protected]$ cc -Wall -O2 readstruct.c 
[email protected]$ time ./a.out 
Sizeof array[0] is 312 
Read 981467136/ 981467136 
Wrote 981467136/ 981467136 

real 0m3.972s 
user 0m1.689s 
sys  0m0.782s 
이제

, 내가 전화하지 것이다 4 초에 읽기 및 쓰기 900MB 느림. 대부분의 사용자 CPU는 sprintf() 호출에 의해 소비되었을 수 있습니다.

관련 문제