리눅스는 거의 모든 것을 파일로 표현하고, 파일로 다룬다.
그렇기에 리눅스 시스템 프로그래밍에서 파일 입출력은 굉장히 중요한 부분이다.
파일을 다루는 가장 기본적인 리눅스 시스템 콜을 하나씩 알아볼 것이다.
파일을 조작(읽거나 쓰는) 하기 전에 반드시 열어야 한다.
리눅스 커널은 파일 테이블이라고 하는 프로세스 별로 열린 파일들을 관리한다.
이때 이 파일들은 파일 디스크립터로 인덱싱되어 관리된다.
파일 디스크립터는 종종 fd 라고도 많이 불리는데, 이 테이블에는 다양한 파일의 정보가 담겨있다.
이 파일 디스크립터는 사용자 영역과 커널 영역 모두에서 프로세스 내의 고유한 식별자로 사용된다.
먼저 파일을 열기 위한 방법에 대해 알아보자.
파일에 접근하는 가장 기본적인 방법은 read(), write()등의 시스템 콜 함수를 사용하는 방법이다.
하지만, 앞에서도 말했듯이 파일에 접근(또는 조작) 하기 위해서는 항상 파일을 열어야 한다.
파일을 접근하기 위해서는 open() 또는 creat() 시스템 을 사용해서 파일을 열 수 있다.
하지만 열었다면 가장 중요한 것!! 모든 사용을 마쳤다면 close()를 이용해 닫아 주는 것!
open() 시스템 콜을 이용하여 파일을 열고 파일 디스크립터를 얻어보자.
위의 소스코드를 참고해보자. open()시스템 콜을 사용하여 파일을 열고 있다.
이때, open() 시스템 콜은 fcntl.h 시스템 콜에 있다.
open() 시스템 콜의 형태는 아래와 같다.
int open (const char *FILENAME, int FLAGS[, mode_t MODE])
시스템 콜 함수의 인자들을 분석하면 아래와 같다.
인자명 |
설명 |
FILENAME |
열려고 하는 대상 파일의 이름 |
FLAGS |
파일을 열 때 적용되는 열기 옵션 |
MODE |
파일 열 때의 접근 권한 설명 |
위의 입력 인자를 잘 숙지해 두자.!
Open() 시스템 콜 함수로 파일을 열게 되면 파일 디스크립터를 반환하게 된다.
하지만, 파일 열기에 실패하게 되면 파일 디스크립터는 -1(음수)를 반환하게 된다.
파일 열 때 적용되는 옵션 중 다음 3가지 중 하나는 꼭 포함해야 한다.
FLAG 명 |
모드 |
O_RDONLY |
오직 읽기 전용으로 파일 열기 |
O_WRONLY |
오직 쓰기 전용으로 파일 열기 |
O_RDWR |
일기와 쓰기 모드로 파일 열기 |
현재 위의 소스를 보면 나는 쓰기 전용으로 파일을 열었다는 것을 알 수 있다.
뒤에 O_CREAT와 O_TRUNC Flag가 포함되어 있는 것을 볼 수 있다. 하지만 2가지 flag는 포함되지
않아도 파일을 열 수 있다. 하지만, 파일이 존재한다는 가정하에다.
소스코드가 있는 디렉토리 내에 opentest라는 파일이 존재한다면 O_CREAT 플래그가 없어도 된다.
하지만 존재하지 않는다면, 파일 디스크립터가 -1이 반환 될 것입니다.
그렇기에 파일이 존재하지 않은 상황이 있다면 생성하여 파일을 열고 싶다면 O_CREAT 플래그를
추가하는게 안전하고 좋다.
FLAG에 들어갈 수 있는 인자는 다음에 한번 정리하겠다.
MODE 인자는 새로운 파일의 소유자?? 권한??을 설정해 주는 것이다.
파일을 생성하면 새로 만들어진 파일의 접근 권한은 mode 인자에 따라 설정된다.
open() 시스템 콜에 mode 인자를 입력하지 않으면 파일을 생성할 때 mode를 점검하지 않으므로 파일을
쓰기 상태로 열었지만, 파일을 접근 권한이 읽기 전용인 경우처럼 모순되는 결과 초래할 수 있다.
mode 인자는 8진수 비트 집합으로 접근 권한이 설정된다.
아래가 mode 인자들을 정리한 것이다.
mode | 권한 |
S_IRWXU |
소유자에게 읽기, 쓰기, 실행 권한이 있다. |
S_IRUSR |
소유자에게 읽기 권한이 있다. |
S_IWUSR |
소유자에게 쓰기 권한이 있다. |
S_IXUSR |
소유자에게 실행 권한이 있다. |
S_IRWXG |
그룹에게 읽기, 쓰기, 실행 권한이 있다. |
S_IRGRP |
그룹에게 읽기 권한이 있다. |
S_IWGRP |
그룹에게 쓰기 권한이 있다. |
S_IXGRP |
그룹에게 실행 권한이 있다. |
S_IRWXO |
그 외 모든 사용자에게 읽기, 쓰기, 실행 권한이 있다. |
S_IROTH |
그 외 모든 사용자에게 읽기 권한이 있다. |
S_IWOTH |
그 외 모든 사용자에게 쓰기 권한이 있다. |
S_IXOTH |
그 외 모든 사용자에게 실행 권한이 있다. |
위의 연산을 OR을 이용하여 중복하여 다양하게 설정할 수 있다.
하지만, 위의 인자를 0664와 같이 진수로 바로 설정할 수 도 있다.
총 3가지, 소유자, 그룹, 그 외 모든 사용자로 권한을 설정해 줄 수 있는데,
위에서 설명했듯이 8진수로 표현할 수 있다고 했다.
코드의 664가 8진수로 표현된 권한이다.
664 => 110 110 100
앞에 부터 소유자, 그룹, 그외 모든 사용자이며 제일 위의 코드와 동일한 조건을 갖는다.
그럼 Open() 시스템 콜이 아닌, 바로 파일을 생성할 수 있는 CREAT() 시스템 콜을 알아보자.
이제 좀 이해하기 쉽지 않나?? Open() 시스템 콜과 달라진 점은 하나이다.
시스템 콜 함수 입력인자에 Flag가 없다. 왜 그럴까?
Open()시스템 콜 시 O_WRONLY | O_CREAT | O_TRUNC 조합이 너무 일반적이라서 이다.
무슨말인지 모르겠는가?? 그럼 creat시스템 콜의 원형을 확인해 보면 아래와 같다.
929 /* 930 * For backward compatibility? Maybe this should be moved 931 * into arch/i386 instead? 932 */ 933 SYSCALL_DEFINE2(creat, const char __user *, pathname, int, mode) 934 { 935 return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode); 936 }
보이는가? creat 함수 내에 open 시스템 콜 함수가 호출 되며, O_WRONLY | O_CREAT | O_TRUNC
설정이 되어 있다.
그러므로, creat() 시스템 호출이나, open() 시스템 콜 호출이나 flag 인자 설정만 해준다면 동일하게 사용할 수 있다는 것이다.
open()이나 creat()나 모두 파일 열기 또는 생성에 성공하면 파일 디스크립터를 반환하게 되고,
에러가 발생하게 되면 둘다 -1을 반환하게 된다.
꼭!! 위의 코드에는 close() 시스템 콜이 없지만,
항상 파일을 열었다면 닫아줘야 한다는 것 잊지 말자 !!
'Linux > System Programming' 카테고리의 다른 글
[파일입출력] 3. write()로 파일에 쓰기 (2) | 2015.02.03 |
---|---|
[파일입출력] 2. read()로 파일 읽기 (2) | 2015.02.01 |
fork (0) | 2013.05.01 |
프로세스 생성과 종료 (0) | 2013.05.01 |
ubuntu 12.04에서 gcc-3.4 설치하기 (0) | 2012.10.13 |