[리눅스 시스템 프로그래밍] 3.4 lseek

파일 입출력 작업을 할 때 lseek 함수를 이용하여 원하는 위치로 이동할 수 있습니다. 현재 작업하고 있는 파일의 시작 위치에서 상대적 거리를 파일 offset이라 부르며 lseek 함수를 이용하면 파일의 시작 위치나 현재 위치, 파일의 끝에서 상대적 거리로 이동할 수 있습니다. 하지만 FIFO나 pipe처럼 특수한 파일은 lseek를 허용하지 않습니다.

#include <sys/types.h>

#include <unistd.h>

off_t lseek(int fd, off_t offset, int whence);

반환 값: 함수를 수행한 이후에 새로운 offset, 실패 시 -1

whence

SEEK_SET: 파일의 시작 위치를 기준

SEEK_CUR: 파일의 현재 작업 위치를 기준

SEEK_END: 파일의 끝을 기준

다음은 lseek 함수의 리턴값을 확인하여 lseek 함수를 사용할 수 있는 파일인지 확인하는 코드입니다.

//ex_ enable_lseek.c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argc,char **argv)
{
    int fd = 0;
    if(argc != 2)
    {
        fprintf(stderr,"usage: %s <filename>\n",argv[0]);
        return 1;
    }
    fd = open(argv[1],O_RDONLY);
    if(fd == -1)
    {
        perror("failed open.");
        return 1;
    }
    if(lseek(fd, 0, SEEK_CUR)==-1)
    {
        printf("can't lseek %s file. \n",argv[1]);
    }
    else
    {
        printf("can lseek %s file. \n",argv[1]);
    }       
    close(fd);
    return 0;
}
[그림 3.4] ex_enable_lseek 실행 화면
[그림 3.4] ex_enable_lseek 실행 화면

 다음은 루트 계정으로 정규 파일과 터미널 장치 파일을 인자로 테스트 화면입니다.

lseek를 이용하여 파일의 끝보다 뒤로 이동한 후에 쓰기 작업을 하면 파일의 크기는 커지면서 빈 공간(hole)이 생깁니다. 내용을 확인하면 빈 공간(hole)은 ‘\0’로 보입니다.

다음은 새로운 파일을 생성한 후 lseek 함수 호출 후에 1바이트 더미 내용을 write하여 Hole을 만드는 예제 코드입니다.

// ex_hole.c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argc,char **argv)
{
    int fd = 0;
    if(argc != 2)
    {
        fprintf(stderr,"usage: %s <filename>\n",argv[0]);
        return 1;
    }
    fd = open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0644);
    if(fd == -1)
    {
        fprintf(stderr,"failed open %s\n",argv[1]);
        return 1;
    }
    if(lseek(fd, 20, SEEK_CUR)==-1)
    {
        printf("can't lseek %s file. \n",argv[1]);
    }
    else
    {
        char dummy='a';
        write(fd,&dummy,1);
    }       
    close(fd);
    return 0;
}

컴파일 한 후에 이를 실험하면 다음처럼 빈 공간이 있는 파일이 생긴 것을 확인할 수 있습니다. 참고로 od 명령은 파일의 내용을 8진수로 dump 하여 보여주며 -c 옵션을 사용하면 ASCII 코드를 확인할 수 있습니다. 그리고 du 명령은 사용 용량을 확인할 수 있어요. 자세한 사항은 man od와 man du로 확인하세요.

[그림 3.5] ex_hole 실행 화면
[그림 3.5] ex_hole 실행 화면

앞으로 소스 코드를 표현할 때 공통적으로 사용하는 내용은 #include “eh.h”로 표시할게요. 그리고 새로운 헤더 파일을 포함할 필요가 있으면 무엇을 추가하였는지 알리기로 하겠습니다.

현재 eh.h 파일의 내용은 다음과 같습니다.

// eh.h
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <stdlib.h>