카테고리 없음

[Link] Linux - fcntl File control

벅스바니 2010. 1. 20. 00:58

fcntl- 파일 서술자(file descriptor)
int fd
:: 제어하기를 원하는 파일의 서술자를 지정하는 매개변수입니다.

리눅스 시스템에서모든 프로세스는 0, 1, 2 라는 3개의 파일 서술자는 미리 정해져있습니다.
각각 입력(0), 출력(1), 에러(2)를 나타냅니다.
파일 서술자 리스트는 각 프로세스마다 독립적이며,
open() 함수를 이용해 파일을가져오거나, 만들며
그 리턴값으로 파일 서술자 값(fd)을 얻을 수 있습니다.
또한, IPC 에서 쓰이는 pipe()나 socket()를 이용해서도 파일 서술자 값을 추가할 수 있습니다.





int
cmd:: 파일 서술자에게 원하는 명령을 넣는 매개변수입니다.

F_DUPFD :: long arg인자보다 크기가같거나, 같은 파일 서술자가 있다면 그보다 큰 값중에
가장 작은 파일 서술자 값을 찾아, 복사본을 만들어 준다.
복사될 파일 지정자를사용자가 정해주는 dup(2)과는 엄밀히 다르다.
두 파일 서술자는 잠금(lock), 파일위치 포인터, flag 들을 공유한다.
(서술자중하나에서 lseek시스템콜에 의해파일 위치가 변경되면,
위치는 또다른 것에 변경될 수 있다.)
이 서술자들은 close-on-exec 플래그를 공유하지 않지만,
복제본의 close-on-exec 플래그는 off상태(실행중 종료되지 않는 상태) 가 된다.
return :: 새로운 기술자를 반환한다.

//
close-on-exec란 ?
//일반적으로 exec계열 함수는, 사용시 모든 파일 서술자를 새로 바뀔 프로그램에게 상속합니다.
//기본적으로 off 되어있는exec-on-exec 플래그가 on이 된다면 (1이 된다면) 상속되지 않음

F_GETFD:: close-on-exec 을 읽는다.
FD_CLOEXEC flag를 넘겨 받는다.만일 FD_CLOEXEC 비트가 0일시,
파일은 exec 계열 함수를 사용할시 모든 서술자는열린 상태로 상속되고,
그렇지 않으면파일 서술자를 상속하지 않는다.
return :: Flag값을 반환한다.

F_SETFD:: close-on-exec 플래그를 사용자가 long arg 매개변수를 이용하여설 정한다.

F_GETFL:: 파일 서술자의 flag를 읽는다. (open(2) 에 의해 설정된 모든 플래그들을 리턴한다.)
return :: Flag값을 반환한다.

F_SETFL:: 파일 서술자의 flag를 사용자가 long arg 매개변수를 이용하여 설정한다.
오직 O_APPEND, O_NONBLOCK, O_ASYNC 만이 설정될 수 있다.
다른 flag들은변경할 수 없다. (ex : O_RDONLY, O_WRONLY.. 등)
(플래그 의미가 궁감하시다면
LINK_로.. )
dup(2), fork(2)로 만들어진 동일한 파일 기술자의 복사본들은플래그를 공유한다.

F_GETLK 와 F_SETLK는 임의의 파일에 잠금을 관리하는데 사용된다.
원하는 잠금 설정을 사용할때, 3번째 인자에 flock 구조체의 포인터형을 넣는다.

F_GETLK:: 잠금을 얻을 수 없도록 제어하는 flock 구조로 리턴하거나, 다른 장애가 없다면
잠금의 l_type 필드를 F_UNLCK 으로 설정한다.

F_SETLK::l_type 이 F_RDLCK 혹은 F_WRLCK 일때, 잠금이 설정되고
l_type 이 F_UNLCK 일때는 잠금이 해제된다.
다른 누군가에 의해 서술자에 대한lock이 설정되면 -1을 리턴한다.

F_SETLKW:: F_SETLK와 같지만,에러를 리턴하는 대신 잠금이 풀리기를 기다린다.
(File _ Set _ lock _ wait 의 약자로 생각하면 쉽다.)
만일 fcntl 이 기다리고 있을때, 시그널이 잡히면 인터럽트 되고,
시그널 처리가 끝난 후에 F_SETLK와동일하게 리턴한다.

F_GETOWN, F_SETOWN, F_GETSIG, F_SETSIG 는 입출력 (I/O) 시그널을 관리하는데 사용한다.
이들을 이용하여 select, poll 없이 비동기적 입출력을 구현할 수 있다.

F_GETOWN:: 파일 서술자 fd에서 일어나는 이벤트에 대한 SIGIO와, SIGURG 시그널을 수신하는
프로세스 ID or Group을 얻는다.
return :: 파일서술자 소유자의 값을 반환한다.

F_SETOWN:: SIGIO, SIGURG 시그널을 수신하는 프로세스 ID or Group을 설정한다.

F_GETSIG:: 입출력(I/O) 이 가능해질 때,시그널이 전송되도록 한다.
제로값은 SIGIO가 전송되었음을 뜻하고, 다른값은 대신 보내진 시그널이다. (SIGIO포함)
return :: 읽기,쓰기가 가능해졌을 때 전송된 시그널 값, SIGIO 행위에 대한 zero

F_SETSIG:: 입출력(I/O) 이 가능해질 때, 신호를 전송하도록 설정한다.
제로가 아닌 값으로 F_SETSIG를 사용하고, SA_SIGINFO (sigaction 참조LINK_)를 설정하여
I/O 이벤트에 대한 입출력 정보가 siginfo_t 내로 전달되게 할 수 있다.
si_code 필드는 소스가 SI_SIGIO 라는 것을 가리키고,
si_fd 필드는 파일 서술자와 이벤트를 관련시킨다.



================================= 예제 =================================

/*
* 아래에 있는 소스는 하나의 프로그램입니다.
* 하나의 프로그램 안에 3개의 예제가 묶여져있는 형태입니다.
* 내용이 바뀌는 부분은 슬러쉬 // ----- // 를 이용하여 구분하였습니다.
*/


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


intmain(void){

intfd;
fd = open("
test.txt",O_RDONLY|O_CREAT|O_APPEND,0755);

//////////////////////////////////////////////////////////////////////////////////////

intfd_dup1 = fcntl(fd,F_DUPFD,100);
intfd_dup2 = fcntl(fd,F_DUPFD,100);

printf("fd_dup1 :: %d\n",fd_dup1);//100 출력
printf("
fd_dup2 :: %d\n",fd_dup2);//101 출력
// F_DUPFD는 첫번째 인자를 복사하여, 3번째 매개변수로도
// 사용하게 끔 하는 함수이다. 3번째 인자와 같은 다른 서술자가
// 존재한다면, 그보다 큰것중에 가장 작은게 선택된다.

///////////////////////////////////////////////////
//execl 계열 함수를 사용할때에, 파일서술자를 상속하게 됩니다.
//하지만close-on-exec가 on이 되어있다면 상속하지 않습니다.
//파일서술자 상속 여부를 설정하는 부분이 담긴 예제 입니다.

int
flag = fcntl(fd,F_GETFD, 0);
if( flag &
FD_CLOEXEC)
printf("
close-on-exec on\n");
else
printf("
close-on-exec off\n");

fcntl(fd,F_SETFD,FD_CLOEXEC);//F_SETFD를 이용하여
flag = fcntl(fd,F_GETFD,0);//close-on-exec를 on으로 바꿉니다.
//더이상파일서술자를 상속하지 않는 상태로 변경
if( flag ==FD_CLOEXEC)
printf("
close-on-exec on\n");
else
printf("
close-on-exec off\n");

//////////////////////////////////////////////////

intstat_flags;
intaccess_flags;

stat_flags = fcntl(fd,F_GETFL, 0);//파일에 걸린 플레그들을 가져옵니다.
access_flags = stat_flags &
O_ACCMODE;// O_ACCMODE는 access flag들의 모든 합입니다.
//fd가 가리키는 파일이 가지는 모든 핸들과,
// access flag를 앤드연산하면,
// 파일이 가지는 access flag들만 남겠죠?
// access flag는 O_RDONLY, O_WRONLY, O_RDWR을 말합니다.

if (access_flags ==O_RDONLY) printf("O_RDONLY");
else if (access_flags ==
O_WRONLY) printf("O_WRONLY");
else if (access_flags ==
O_RDWR) printf("O_RDWR");//access flag 출력

if (stat_flags &O_CREAT) printf("| O_CREAT");
if (stat_flags &
O_EXCL) printf("| O_EXCL");
if (stat_flags &
O_TRUNC) printf("| O_TRUNC");
if (stat_flags &
O_APPEND) printf("| O_APPEND");
if (stat_flags &
O_ASYNC) printf("| O_ANSYC");
if ((stat_flags &
O_NONBLOCK) ==O_NONBLOCK)
printf("
| O_NONBLOCK");
else
printf("
| BLOCKING");
printf("
\n");

return0;
}

================================= 예제 =================================




(파일 이름이 real인건 의미 없습니다.)

파일flag 부분에 나오는결과에 의문이 있으신분이 있을것입니다.
fd = open("
test.txt",O_RDONLY|O_CREAT|O_APPEND,0755);
이렇게 파일 서술자를 열었는데, O_CREAT, O_APPEND는 왜 안뜨는것일까?
O_TRUNC (파일 초기화 시킨후 열기)도 flag에 추가해줘도 F_GETFL 으로 가져온
파일 서술자의 플레그 값에는 보이지 않습니다.
그 이유는, O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC 플래그는
다른 서술자가 파일을 가리킬 때 (혹은 열때), 그 방식을 지정하는 플래그 입니다.
파일 속성이 아니라 단순히 파일 서술자의 연산 (혹은 제어) 방식일 뿐이라는 말입니다.
따라서, 파일이 서술자에 의해 열리고 난 뒤에는 의미가 없는 플래그 이기 때문에,
F_GETFL로 얻어올 수 없습니다.

:: 열려있는 파일의 속성과는 전혀 상관없는 플래그는 F_GETFL로 얻어올 수 없다.