가끔 컴공 과제글 올라오면 open 시스템 콜이 제대로 동작하지 않는다는 말이 있음. 파일 이름도 제대로 되었고 권한 문제도 아니라는거임. 근데 파일 디스크립터 값이 0 이하가 나옴. (에러 발생) 이것땜에 시스템 프로그래밍 포기하는 사람들도 있을거 같음. 왜 그런지 이유를 설명해봄. 일단 유닉스 프로그래머라면 메뉴얼 페이지 정도는 읽을 줄 알아야 함. 최소한 man 2는 시스템 호출이고 3은 라이브러리라는 것만 알면 됨. 그리고 open 시스템 호출에 대한 페이지를 읽으면 금방 해결책이 나온다는 것을 알게됨.

#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);


잘 보면 open 함수가 두가지 형식으로 나눠진다는 것을 알 수 있는데 C에는 함수 오버로딩이라는게 존재하지 않는다는 걸 생각하면 이상한 코드가 맞다. 그러나 사실 이 함수는 가변 인자를 받는다. 가변 인자로 하면 타입을 제대로 모르니까 쉽게 이해하기 위해서 두 원형을 같이 써두는 페이지가 많다는 것. (내가 배운 책에는 완벽하진 않지만 가변 인자를 받는것으로 표시되어 있다.)

근데 왜 두가지 형식을 사용하냐고? 왜냐하면 open 함수는 파일을 생성해주는 작업을 하지 않았기 때문이다. 원래는 파일 생성은 creat(2)가 해주고 open은 파일을 열기만 한다. 그러나 이렇게 짜면 불편하니까 open에 추가적으로 인자를 넣어서 생성과 동시에 파일을 열도록 하는 것임. 당연하지만 파일을 생성하려면 권한을 지정해줘야함.

int creat(const char *pathname, mode_t mode);


이것이 creat(2)의 원형이고 잘 보면 open(2)의 두번째 형식과 같은 인자를 받는다는게 보인다.

open(2)에 확장값을 안넣으면 구 버전 방식으로 동작하고 첫번째 형식으로 동작한다. O_CREAT 값을 추가하면 확장된 모드(파일 생성을 겸함)로 동작한다. 그리고 파일 생성에는 파일 권한을 지정해줘야 하므로 가변 인자로 퍼미션 값을 받는다. 만약 이 사실을 모르고 추가적인 인자를 넣어주지 않는다면 잘못된 값을 퍼미션 값으로 읽어서 생성 오류를 내는거임.

너무 장황하게 설명한 것 같지만 핵심만 정리하자면.
open(2)의 두번째 인자에 O_CREAT 값이 포함되면 세번째 인자(creat의 mode_t mode)가 필요하다는 점만 기억하면 됨.