리눅스 파일은 읽거나 쓰기 전에 반드시 열어야 한다. 커널은 파일 테이블이라고 하는 프로세스별로 열린 파일 목록을 관리한다. 이 테이블은 음이 아닌 정수 값인, 파일 디스크립터로 인덱싱되어 있다. 이 테이블(커널)의 각 항목은 열린 파일에 대한 정보를 담고 있으며 여기에는 메모리에 복사된 inode를 가리키는 포인터와 각종 메타데이터가 포함되어 있다. 파일 디스크립터는 사용자 영역과 커널 영역 모두에서 프로세스의 냉의 고유한 식별자로 사용된다. 파일을 열면 파일 디스크립터가 반환된고 이 파일 디스크립터를 관련 시스템 콜의 첫 번째 인자로 넘겨 다양한 연산을 수행한다.
파일 디스크립터는 C의 int형이다. 따라서 각 리눅스 프로세스가 열 수 있는 최대 파일 개수가 정해져 있다. |
파일 디스크립터로 음수를 허용하지 않기 때문에 함수에서 발생한 에러는 음수인 -1을 사용한다. 음수가 아닌 값은 유효한 파일 디스크립터다.
파일 디스크립터는 단순히 일반 파일만 나타내는 것이 아니다. 파일 디스크립터는 장치 파일, 파이프, 디렉터리, 퓨텍스, FiFo, Socket 접근에도 사용되며 모든 것이 파일이라는 유닉스 철학에 따른다. 또한 하나의 속성을 기억하자.
자식 프로세스는 부모 프로세스가 소유한 파일 테이블의 복사본을 상속받는다.
- 파일 열기
파일에 접근하는 가장 기본적인 방법은 read(), write() 시스템 콜이다. 하지만 파일에 접근하기에 앞서 open()이나 creat() 시스템 콜을 사용해서 파일을 열어두고, 다 쓴 다음에는 close() 시스템 콜로 파일을 닫아야 한다.
- open() 시스템 콜
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *name, int flags);
int open(const char *name, int flags, mode_t mode);
파일의 경로 이름이 name인 파일을 파일 디스크립터에 맵핑하고, 성공하면 파일 디스크립터를 반환한다. 파일 오프셋은 파일의 시작지점인 0으로 설정되며, flags로 지정한 접근 모드로 열린다. flags 매개 변수에 비트 OR 연산으로 다음 값 중 하나 이상을 추가해서 열기 동작을 변경 가능.
- open() 플래그
flags 인자는 O_RDONLY, O_WRONLY, O_RDWR 중 하나를 포함해야한다. 각 플래그는 읽기 전용, 쓰기 전용, 읽기와 쓰기 전용이다. 또한 비트 OR 연산으로 다음과 같은 명령어를 함께 사용할 수 있다.
=
O_APPEND 덧붙이기 모드로, 파일 열고 난 후의 파일 오프셋이 파일 제일 끝을 향한다. |
O_ASYNC 특정 파일에서 읽기나 쓰기 가능해질 때 시그널(SIGIO)이 발생한다. 터미널이나 소켓에만 사용할 수 있다. |
O_CLOEXEC 새 프로세스가 실행하면 이 파일은 자동으로 닫힌다. 새 프로세스가 생성되면서 기존의 파일 디스크립터를 복사해서 생기는 경쟁산태를 사전에 방지할 수 있다. 리눅스 커널 2.6.23에서 사용 가능 |
O_CREAT 파일이 없으면 새로 만든다. |
O_DIRECT 직접 입출력을 수행하기 위해 파일 연다. |
O_DIRECTORY 디렉토리가 아니면 open을 실패한다. opendir() 라이브러리 호출을 내부적으로 사용한다.? |
O_EXCL O_CREAT와 함께 사용한다면, 기존 파일 존재할 때 실행되지 않는다. 경쟁상태 회피용 |
O_LARGEFILE 2기가바이트 초과 파일을 열기 위해 64bit 오프셋 사용 |
O_NOATIME+ 읽기에 의해서 파일의 마지막 접근 시간이 갱신되지 않도록 한다. (커널 >= 2.6.8 ) |
O_NOCTTY 터미널 디바이스를 가리키면 프로세스에 현재 제어 중 터미널이 없더라도 프로세스의 제어 터미널이 되지 않는다.[?] |
O_NOFOLLOW 심볼릭 링크라면 실패한다. 디렉터리가 심볼릭이라면 따라가서 파일을 열고, 열려고 하는 파일이 심볼릭 링크일 경우 실패한다. |
O_NONBLOCK 파일을 논플로킹 모드로 연다. open() 호출이나 다른 연산은 입출력 과정에서 프로세스를 막고 있지 않는다. FIFO용만 사용한다. |
O_SYNC 파일을 동기식 입출력용으로 연다. 데이터를 물리적으로 디스크에 쓰기 전까지 쓰기 연산이 완료되지 않는다. 일반적인 읽기 연산은 이미 동기식이므로 읽기와 관련해서 이 플래그는 영향을 미치지 않는다. |
O_TRUNC 파일이 존재하고, 일반 파일이며 flags 인자에 쓰기가 가능하도록 명시되어 있으면 파일 길이가 0으로 잘라버린다. FIFO나 터미널 디바이스에서는 해당 명령어의 동작은 무시된다. 파일을 자르려면 쓰기 권한이 있어야 함으로 O_RDONLY와 함께 쓰이는 경우 동작하지 않는다. |
'Linux > Linux System Programming' 카테고리의 다른 글
프로세스는 뭘까? - 정의 (0) | 2022.12.08 |
---|---|
ftrace란? (0) | 2022.11.24 |
dump_stack()함수 (0) | 2022.11.20 |
커널 디버깅 - printk (0) | 2022.11.20 |
커널 로그 확인 방법 (0) | 2022.11.20 |