/*
* http://sosal.tistory.com/
* made by so_Sal
*/
fcntl - File control
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
(flock 구조체에 대해서는 게시하지 않았습니다. )
첫번째 매개변수 fd부터 보겠습니다.
fd - 파일 서술자(file descriptor)
ㄴ 제어하기를 원하는 파일의 서술자를 지정하는 매개변수입니다.
리눅스 시스템에서 모든 프로세스는 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>
int main(void){
int fd;
fd = open("test.txt", O_RDONLY | O_CREAT | O_APPEND , 0755);
//////////////////////////////////////////////////////////////////////////////////////
int fd_dup1 = fcntl(fd,F_DUPFD,100);
int fd_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");
//////////////////////////////////////////////////
int stat_flags;
int access_flags;
stat_flags = fcntl(fd, F_GETFL, 0); //파일에 걸린 플레그들을 가져옵니다.
access_flags = stat_flags & O_ACCMODE; // O_ACCMODE는 access flag들의 모든 합입니다.
// fd가 가리키는 파일이 가지는 모든 핸들과,
// O_ACCMODE를 앤드연산하면,
// 파일이 가지는 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");
return 0;
}
================================= 예제 =================================
(파일 이름이 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로 얻어올 수 없다.
'Linux > Linux_programing' 카테고리의 다른 글
Linux - real id, effective id 사용자 id (5) | 2010.01.27 |
---|---|
Linux - dirent.h 함수와 구조체, find 프로그램 맛보기 (0) | 2010.01.20 |
IPC - 03. pipe() 를 통한 프로세스 통신 (3) | 2009.12.18 |
Socket 05. option 소켓 옵션 getsockopt() setsockopt() (0) | 2009.11.06 |
Socket 04. close() shutdown() 소켓 서술자 닫기 (0) | 2009.11.06 |