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

[리눅스/유닉스 시스템 프로그래밍] dup, dup2

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

3.6 dup, dup2

 리눅스 시스템에서는 열려진 파일의 디스크립터를 복제하는 dupdup2 함수를 제공합니다.

#include <unistd.h>

int dup(int oldfd);

int dup2(int oldfd, int newfd);

반환 값: 새로운 파일 디스크립터, 실패 시 -1

 

 먼저 dup 함수는 입력 인자로 열려진 파일 디스크립터를 전달하면 같은 물리적 파일을 연 새로운 파일 디스크립터를 반환합니다. 이와 같이 열면 두 개의 파일 디스크립터는 커널의 같은 파일 테이블 엔트리를 참조합니다. 파일의 작업 offset은 파일 테이블 엔트리에 기억하므로 두 개의 파일 디스크립터로 접근하는 파일 작업의 오프셋은 같습니다.


dup로 파일 디스크립터를 복제할 때 열려진 파일의 데이터 구조

[그림 3.3] dup로 파일 디스크립터를 복제할 때 열려진 파일의 데이터 구조


 예를 들어 hello 파일에 abcdefghijklmnopqrstuvwxyz라는 내용이 있다고 가정합시다. 이 파일을 열어서 fd1에 파일 디스크립터를 기억합니다. dup 함수를 이용하여 fd1을 복제한 파일 디스크립터를 fd2에 기억합니다. fd1으로 10바이트를 읽으면 abcdefghij까지 읽어옵니다. 이 때 fd2 10바이트를 읽어오면 두 개의 파일 디스크립터는 같은 파일 테이블의 엔트리를 참조하므로 읽어 온 다음 위치에 있는 klmnopqrst를 읽어옵니다.

// ex_dup.c

#include "eh.h"

int main(int argc,char **argv)

{

    int fd1 = 0, fd2=0;

    char buf[10+1]="";

    if(argc != 2)

    {

        fprintf(stderr,"usage: %s [file name]\n",argv[0]);        return 1;

    }

    fd1= open(argv[1],O_RDONLY);

    if(fd1 == -1)

    {

      fprintf(stderr,"failed open %s\n",argv[1]);      return 1;

    }

    fd2= dup(fd1);

    if(fd2 == -1)

    {

      perror("failed dup");      return 1;

    }

    read(fd1,buf,10);

    printf("fd1:%s\n",buf);

    read(fd2,buf,10);

    printf("fd2:%s\n",buf);

    close(fd1);

    close(fd2);

    return 0;

}

$ cat hello

abcdefghijklmnopqrstuvwxyz

$ ./ex_dup hello

fd1:abcdefghij

fd2:klmnopqrst

 dup2 함수는 첫 번째 인자로 열려진 파일 디스크립터를 전달하고 두 번째 인자로 파일 디스크립터를 전달하면 첫 번째 인자로 열려진 파일 디스크립터가 참조하는 파일 테이블 엔트리를 두 번째 전달한 파일 디스크립터도 참조합니다. 만약 두 번째 인자로 전달한 파일 디스크립터가 열려진 파일 디스크립터일 때는 먼저 닫고 난 후에 복제합니다.

 

 보통 dup2 함수는 정규 파일을 표준 출력으로 사용할 때 때 많이 사용합니다.

 

 예를 들어 dup2(fd, STDOUT_FILENO);를 호출한 후에 printf 함수를 호출하면 fd로 연 파일에 쓰여집니다.

// ex_dup2.c

#include "eh.h"

int main(int argc,char **argv)

{

    int fd = 0;

    if(argc != 2)

    {

        fprintf(stderr,"usage: %s [file name]\n",argv[0]);        return 1;

    }

    fd= open(argv[1],O_WRONLY);

    if(fd == -1)

    {

      perror("failed open ");      return 1;

    }

    if(dup2(fd,STDOUT_FILENO) == -1)

    {

      perror("failed dup2");      return 1;

    }

    printf("hello world\n");

    close(fd);

    return 0;

}

$ ./ex_dup2 yahoo

$ cat yahoo

hello world


반응형