프로그래밍 기술/리눅스(Unix) 시스템 프로그래밍

[리눅스/유닉스 시스템 프로그래밍] fnctl, sync, fsync

언제나휴일 2016. 4. 5. 23:12
반응형

3.7 fnctl

 리눅스 시스템에서는 열려진 파일의 속성을 가져오거나 설정할 때 fcntl 함수를 사용합니다.

#include <unistd.h>

#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* int arg */);

반환 값: cmd에 따라 다름, 실패 시 -1

cmd

  F_DUPFD : 파일 디스크립터를 복제함

  F_GETFD, F_SETFD : 파일 디스크립터 flags를 가져오거나 설정

  F_GETFL, FSETFL : 파일의 status flags를 가져오가나 설정

  F_GETOWN, F_SETOWN :

    SIGIO SIGUSR 시그널을 수신하는 프로세스 ID 혹은 프로세스 그룹 ID를 가져오거나 설정

  F_GETLK, F_SETLK, F_SETLKW : 레코드 lock을 가져오거나 설정

 

 fcntl 함수는 cmd 인자에 따라 파일의 속성을 가져오거나 설정할 수 있습니다. 앞으로 함수 이름이 cntl로 끝나는 것을 살펴보시면 여러 가지 기능을 cmd 인자에 따라 수행하는 함수라는 것을 알 수 있습니다.

 

 다음은 fcntl 함수에 F_GETFL 인자를 전달하여 접근 모드를 확인하는 예제 코드입니다.

#include "eh.h"

int main(int argc,char **argv)

{

    if(argc !=2){    printf("Usage %s [file descriptor]\n",argv[0]);    exit(0);    }

    int val=0;

    val = fcntl(atoi(argv[1]),F_GETFL,0);

    if(val<0){    perror("failed fcntl");    exit(0);    }

    int accmode = val & O_ACCMODE;

    switch(accmode)

    {

        case O_RDONLY: printf("read only\n"); break;

        case O_WRONLY: printf("write only\n"); break;

        case O_RDWR: printf("read write\n"); break;

    }

    return 0;

}

 

 

3.8 sync, fsync

 프로세스가 파일에 쓰기 작업을 요청하면 운영체제에서는 요청한 작업을 수행합니다. 그런데 시스템에서는 효율이 높은 입출력을 위해 프로세스의 쓰기 요청이 오면 버퍼에 기록해 두었다가 처리합니다. 따라서 프로세스에서 쓰기 요청한 시간과 실제 디스크에 쓰여지는 시간은 차이가 발생할 수 있습니다.

 

 만약 버퍼에 기록한 정보를 실제 디스크에 쓰는 것을 완료하기를 원한다면 sync 함수나 fsync, fdatasync 함수를 사용하세요.

#include <unistd.h>

void sync(void);

int fsync(int fd);

int fdatasync(int fd);

반환 값: 성공 시 0, 실패 시 -1

 

 sync 함수는 모든 파일 쓰기 작업에서 기록한 정보를 디스크에 반영하라는 것입니다. 하지만 이 함수를 호출하였을 때 시스템에 반영하라는 명령을 내리는 것이라 함수가 끝났다고 실제 디스크에 쓰여졌다는 것을 보장할 수는 없습니다. 물론 충분한 시간이 흐른 뒤에는 디스크에 반영한다는 것은 보장합니다.

 

 fsync fdatasync 함수는 물리적인 디스크에 반영하고 난 후에 반환하므로 함수가 끝났고 반환값이 -1이 아니면 실제 디스크에 쓰여졌다는 것을 보장할 수 있습니다. 그리고 fdatasync 함수는 버퍼의 내용을 디스크에 쓰는 것만을 보장하지만 fsync는 버퍼의 내용 뿐만 아니라 변경한 파일 속성 등의 메타 데이터도 반영합니다.


반응형