기본 콘텐츠로 건너뛰기

리눅스에서 2G 이상 파일 다루기

리눅스 커널 2.4부터 2기가 파일제한이 풀렸다.

커널만 지원한다고 다 해결될 일이 아니다. 표준함수를 쓴다면 표준 라이브러리(glibc에 뭉쳐 있겠지?)가 지원해야한다. 다행히 표준 라이브러리는 2기가 이상 파일(large file이라고 한다)을 지원한다.

단, 다른 이름으로 제공한다. 예를 들어 fopen이 있으면 fopen64가 따로 있다. off_t 역시 off64_t가 따로 존재한다. 또한 이 라이브러리를 사용하고 싶다면 _LARGEFILE_SOURCE를 정의해야한다. 즉 컴파일 옵션에 -D_LARGEFILE_SOURCE를 포함해야한다.

ㅡ_-); 불편하다. 그냥 fopen == fopen64 이렇게 쓸 수 없나? 소스 안 고쳐도 되고 말이야.

그래서 _FILE_OFFSET_BITS가 있다. 컴파일 옵션에 -D_FILE_OFFSET_BITS=64를 하면 모든 *64 함수/변수형은 기존 이름으로 바뀐다. 즉 소스에 fopen이라고 쓰더라도 fopen64를 호출한다.

ㅡ_-); 결국 2기가 이상 파일을 쓰려면 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64를 옵션으로 써야한다. (테스트해보니 _FILE_OFFSET_BITS만 64로 정의했어도 잘 돌아간다.)

테스트 코드 (offset.c)
#include <stdio.h>
#include <unistd.h>

int
main(int,char**)
{
        printf("fopen: %p\n", fopen);
        printf("fopen64: %p\n", fopen64);
        printf("size of off_t: %d\n", sizeof(off_t));
        return 0;
}

컴파일 결과
32bit CPU
$ gcc -o offset offset.c
$ ./offset
fopen: 0x80483dc
fopen64: 0x80483cc
size of off_t: 4
(fopen과 fopen64의 함수 주소 값이 다르다)

$ gcc -o offset offset.c -D_FILE_OFFSET_BITS=64
$ ./offset
fopen: 0x80483a8
fopen64: 0x80483a8
size of off_t: 8
(fopen과 fopen64의 함수 주소 값이 같다)

64bit CPU (x86_64)
$ gcc -o offset offset.c
$ ./offset
fopen: 0x4004f0
fopen64: 0x400510
size of off_t: 8
(fopen과 fopen64의 함수 주소 값이 다르다)

$ gcc -o offset offset.c -D_FILE_OFFSET_BITS=64
$ ./offset
fopen: 0x4004c0
fopen64: 0x4004c0
size of off_t: 8
(fopen과 fopen64의 함수 주소 값이 같다)


Fedora Core 6에서 x86_64(64bit cpu) 깔아서 해봤더니 옵션 없을 때 off_t 크기가 8로 나오더군. 그러나 fopen과 fopen64 주소값이 다른 걸로 보아, 될 수 있으면 _FILE_OFFSET_BITS를 세팅해주는 센스를 발휘하는게 좋을 듯 싶다.

댓글

이 블로그의 인기 게시물

Bash Array, Map 정리

Bash에서 Array, Map에 대한 정리. (매번 찾기 귀찮) 찾아보진 않았지만, Bash에서 Array든 Map이든 동일하게 Map(C++에서 Unordered Map)으로 동작하는 것 같다. 왜냐하면, Array의 Index가 연속하지 않아도 동작한다. 그저 Key가 0 이상의 정수인 Map이랑 비슷하게 동작한다. 예) 1, 2, 3, 9, 10 Array # 생성 declare -a empty_array declare -a ar=(haha hoho baba "long string haha hoho") # 접근 echo "ar[0]=${ar[0]}" echo "all as array=${ar[@]}" # 큰따옴표 안에서 각 원소를 따로따로 전달한다. echo "all as one=${ar[*]}" # 큰따옴표 안에서 각 원소를 문자열 하나로 합쳐 전달한다. echo "indexes=${!ar[@]}" echo "indexes=${!ar[*]}" echo "length=${#ar[@]}" echo "length=${#ar[*]}" echo "last=${ar[-1]}" echo "last=${ar[@]: -1}" # 콜론 뒤에 빈 칸이 꼭 필요하다. 옛 방식 # 현재 상황 declare -p ar #(출력) declare -a ar=([0]="haha" [1]="hoho" [2]="baba" [3]="long string haha hoho") ar[100]=hello # 인덱스를 건너 뛰어도 동작한다. declare -p ar #(출력) declare -a ar=([0]="haha" [1]="hoho" [2]="baba" [3]=...

설치한 패키지에서 RPM 추출하기

오래된 패키지를 관리할 저장소가 없어졌고, 기존 패키지로 다른 서버를 세팅해야할 일이 생겼다면 RPM의 리패키지 기능을 이용해보자. $ rpm -e --repackage [PACKAGE_NAME] 위와 같이 리패키지하면, /var/spool/repackage/ 에 생성한 RPM파일이 있다. :-)