개발 · 컴퓨터공학 / / 2021. 9. 29. 23:38

UNIX - system call - dup, fcntl

728x90
반응형

dup(2), dup2(2)

duplicate의 약자로 file descriptor를 복제하는 역할

#include <unistd.h>

int dup(int filedes);
int dup2(int filedes, int filedes2);

// Both return: new file descriptor if OK, -1 on error

dup은 filedes의 값을 복사하여 반환하고, 

dup2는 filedes의 값이 filedes2로 복사된다.

 

newfd = dup(1) /* STDOUT_FILENO #1 */
	== //(같은 맥락의 코드)
newfd = fcntl(1, F_DUPFD, 0);
	!= //(다른 코드)
newfd = 1

위 코드에서 newfd에 file descriptor 3이 들어있다고 가정해보자. dup(1)의 값을 newfd의 대입한다는 것은 file descriptor 1이 가리키는 file table을 file descriptor 3도 가리키게되는 것이다. 그러면서 file table의 count값이 증가한다. count값은 file table을 가리키는 file descriptor의 수를 의미한다.

 

 이후에 알아볼 fcntl system call도 비슷한 맥락이다. fcntl의 세 번째 매개변수 0은 0보다 큰 번호 중 사용되지 않는 가장 작은 번호를 의미하며 0,1,2 는 생성시 정해져있으므로 보통은 3번 file descriptor를 의미한다. 즉 1번 file descriptor가 가리키는 file table을 3번 file descriptor도 가리키도록 하는 동작을 의미한다. 

example

아래의 예시를 보자

fd4 = open(“test”, O_RDONLY); /* fd4 == 4  */

dup2(3, fd4);	/* test’s file descriptor closed */

==
close(fd4);
fcntl(3, F_DUPFD, fd4)

위 코드에서 file descriptor 3번이 이미 open되어있는 아래와 같은 상황이라고 가정하자.

open system call을 통해 fd4에 파일을 할당하면 다음 그림과 같다.

이 상황에서 dup2 system call을 실행하면 fd3이 가리키는 table을 fd4도 가리키게 되므로 

위와 같이 fd4가 fd3의 file table과 같은 table을 가리키게 되고 file table의 count 값도 변하게 된다.

fcntl(2)

file control 각종 파일에 대한 조작이 가능한 system call이다.

#include <fcntl.h>

int fcntl(int filedes, int cmd, ...);

// Returns: depends on cmd if OK (see following), , -1 on error

cmd 의 값으로 아래와 같이 다양한 명령어 설정이 가능하다.

F_DUPFD  : Duplicate an existing descriptor
F_GETFD or F_SETFD  : Get/set file descriptor flags
F_GETFL or F_SETFL  : Get/set file status flags
F_GETOWN or F_SETOWN : Get/set asynchronous I/O ownership
F_GETLK, F_SETLK, or F_SETLKW : Get/set record locks

예를들어 F_DUPFD의 경우 위의 dup system call의 코드에서 본 것처럼 dup과 유사하게 사용할 수 있는 cmd 설정이다.

 

example

예제코드를 보자.

#include <fcntl.h>

int filestatus(int filedes)
{
  int arg1;

  if (( arg1 = fcntl (filedes, F_GETFL)) == -1) // cmd가 F_GETFL인 경우 return이 open 설정
  {
    printf ("filestatus failed\n"); 
    return (-1);
  }

  printf ("File descriptor %d: ",filedes);

  /* 개방시의 플래그를 테스트한다. */
  switch ( arg1 & O_ACCMODE){
    case O_WRONLY: printf ("write-only"); break;
    case O_RDWR:   printf ("read-write"); break;
    case O_RDONLY: printf ("read-only");  break;
    default: printf("No such mode");
  }

  if (arg1 & O_APPEND)
    printf (" -append flag set");

  printf ("\n");
  return (0);
}

위 코드는 input 되는 filedes 매개변수 값이 file descriptor이다. file descriptor 값이 주어지면 해당 fd가 가리키는 file table이 어떤 설정(O_RDONLY | O_WRONLY | O_RDWR 등)으로 open되었는지를 파악하는 코드이다.

 

코드에서 fcntl의 cmd 값을  F_GETFL로 설정한 경우 return value가 file table의 open 설정값이 반환된다. 

switch 문을 보자, <fcntl.h> 헤더에 내장된 O_ACCMODE은 위 코드와 같이 bit wise and연산을 하였을 때 arg1의 정보 중 특정 flag값만을 뽑아낼 수 있도록 정의된 값이다. arg1의 여러 정보중 읽기 쓰기 권한관 관련된 flag만을 추출하여 WRONLY / RDWR / RDONLY flag를 판단한다. 

 O_APPEND의 경우 마찬가지로 append flag가 설정되는 비트에만 1로 처리되어있어 bit and 연산을 통해 flag를 검출할 수 있다.

<fcntl.h> 헤더에는 위처럼 사용할 수 있는 아래와 같은 값들이 정의되어 있다.

O_APPEND
O_DSYNC
O_NONBLOCK
O_RSYNC
O_SYNC
O_ACCMODE
O_RDONLY
O_RDWR
O_WRONLY
728x90
반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유