Unix System Programming 2 - :namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />김성호(moohou) :namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
_________________________________________________________________________
제2장 UNIX 화일 접근 프리미티브
2.1.1. 서론
UNIX 화일 접근 프리미티브
--------------------------------------------
이름 의미
--------------------------------------------
open 읽거나 쓰기위해 화일을 연다.
creat 빈 화일을 생성한다.
close 앞서 열려진 화일을 닫는다.
read 화일로부터 정보를 추출한다.
lseek 화일 안의 특정 바이트로 옮긴다.
unlink 화일을 제거한다.
--------------------------------------------
성공하면 0 , 실패하면 -1 을 돌려준다. 모든 개방된 화일은 프로세스가 종료할때 자동적으로 닫힌다.
2.1.2. open 시스템 호출
존재하는 화일을 읽거나 쓰기전에 반드시 open 시스템호출로 화일을 개방해야 한다.
#include <fcntl.h>
int filedes, flsgs;
char *pathname;
.
.
filedes = open(pathname, flags);
첫번째 인수 pathname은 개방될 화일의 경로이름을 갖고 있는 문자열에 대한 포인터이다. 화일은 open 이 호출되기전에 반드시 존재해야 한다. 그렇지 않으면 오류가 발생한다.
fcntl.h 에서 정의되는 상수
- O_RDONLY 읽기만 허용하는 개방 화일
- O_WRONLY 쓰기만 허용하는 개방 화일
- O_RDWR 읽고 쓰는 것을 허용하는 개방 화일
오류가 발생하면 open은 -1을 돌려준다. 오류는 화일이 존재하지 않을 경우 발생한다. 오류조사(error checking)를 시스템호출을 사용하는 모든 프로그램에 대해서 해 주는 것은 발생할지도 모르는 오류를 고려할때 매우 유익하다.
주의사항(caleats)
1. 수행중인 프로그램에 의해 동시에 개방될 수 있는 화일의 수에는 제한이 있다. (보통20) 또한 존재하는 모든 프로세스에 의해 개방될 수 있는 화일의 수에도 제한이 있다. 이것은 커널안에 있는 표의 크기에 의해 결정된다.
2. 초기 UNIX에는 인클루드 화일 fcntl.h가 존재하지 않았기 때문에 실제 숫자가 flags 인수로서 사용되었다.
2.1.3. creat 시스템 호출
creat 시스템호출은 새로운 화일을 생성하거나 존재하는 화일의 길이를 0 으로 고쳐놓기 위해 사용된다. open 과 같이 creat 호출은 음이 아닌 화일 기술어 또는 오류코드 -1 을 돌려준다.
int filedes, mode;
char *pathname;
.
.
filedes = creat(pathname, mode);
첫번째 인수 pathname은 UNIX 경로이름을 나타낸다. 이것은 새 화일의 이름과 위치, 또는 존재하는 화일의 이름을 지정한다. 두번째 인수 mode 는 정수값을 갖고 화일의 접근 허가(access permission)를 부여한다.
mode 의 값은 화일이 생성될 때만 의미를 갖고, 존재하는 화일의 경우에는 의미를 지니지 못한다. 존재하는 화일의 경우는 원래의 허가를 계속 가지게 된다. creat 는 쓰기 전용으로만 화일을 개방한다는 것에 유의하라.
2.1.4. close 시스템 호출
시스템 호출 close는 open과 반대이다. close 호출 프로세스가 화일에 관련된 작업을 끝냈다는 것을 시스템에 알려준다.
int retval, filedes;
.
.
retval = close(filedes);
close 가 성공하면 0 을 돌려주고, 오류가 발생하면(정당한 화일 기술어를 인수로 갖지 않을 경우) -1 을 돌려준다.
2.1.5. read 시스템 호출
read 는 화일로부터 임의 길이의 문자나 바이트를 호출 프로그램의 제어하에 있는 버퍼로 복사하기 위해 사용된다. 이때 버퍼는 char 의 배열로서 정의된다.
int nread, filedes, n;
char *bufptr;
.
.
nread = read(filedes, bufptr, n);
read 의 첫번째 인수 filedes 는 앞서 호출한 open 이나 creat 에 의해서 만들어진 화일기술어 이다. 두번째 인수 bufptr 은 자료가 복사 되어질 문자 배열에 대한 포인터이다. 새번째 인수는 화일로부터 읽어질 바이트의 수를 가지는 양의 정수값이다.
read 로부터의 복귀값 nread 는 실제로 읽힌 바이트의 수를 나타낸다. read 의 경우, 시스템은 각 호출 후에 읽혀진 바이트의 수만큼 읽기-쓰기 포인터를 전진시킨다. read 호출에 의해 요청된 문자의 수가 화일에 남아있는 문자의 수보다 클 경우 시스템은 남아있는 문자들만 옮기고, 복귀값을 적적하게 고친다.
이제 이후에 호출되는 read 의 복귀값은 0 이 된다. 즉, 남아있는 문자가 하나도 없게 된다. 사실, read 로부터 복귀값이 0 인가를 조사하는 것이 프로그램 안에서 화일의 끝을 조사하는 보통의 방법이다.
2.1.6. write 시스템 호출
write 시스템호출은 read 의 정반대이다. 이 호출은 문자 배열로서 정의된 프로그램 버퍼로부터 자료를 외부화일로 복사한다.
int nwrite, filedes, n;
char *bufptr;
.
.
nwrite = write(filedes, bufptr, n);
n 은 쓰여질 문자의 수인 양수이다. nwrite 로의 복귀값은 쓰여진 문자의 수 또는 오류코드 -1 이다. 실제적으로 -1 이 아니면 nwrite 는 거의 n 과 동일하다. 만약 n 보다 작으면 무언가 잘못된 일이 발생했다. 화일은 처음에 0 바이트 길이로 초기화된 후 write 호출이 있을 때마다 화일의 끝에 자료가 더해진다. 읽기-쓰기 포인터는 마지막 바이트가 쓰여진 후 곧바로 위치를 바꾼다.
2.1.7. copyfile 예
-- 생략
2.1.8. read, write 와 효율성
-- 생략
2.1.9. lseek 과 임의 접근
사용자는 lseek 시스템 호출을 사용하여 읽기-쓰기 포인터의 위치, 즉 다음에 읽거나 쓸 바이트의 위치를 변경할 수 있다. 그래서 lseek 은 화일에 대한 임의 접근을 가능하게 한다.
long newpos, offset, lseek();
int filedes, direction;
.
.
newpos = lseek(filedes, offset, direction);
filedes 는 개방되어 있는 화일의 화일기술어 이다. long 정수형 offset 은 읽기-쓰기 포인터의 새 위치를 결정한다. 이것은 시작위치에 더해질 바이트의 수를 지정한다. 시작위치는 direction 에 의해 결정된다. direction 의 값이 0 이면, offset 이 화일의 맨앞에서부터 더해진다. 값이 1 이면, offset 이 화일포인터의 현재 위치에 더해진다. 값이 2 이면, 화일의 마지막 바이트의 번호에 더해진다.
주의 해야 할 몇가지 주안점.
1. newpos 와 offset 둘다 long 정수형이다.
2. offset 은 음수가 될수 있다.
3. 화일의 끝보다 더 위의 위치를 지정하는 것이 가능하다.
2.1.10. 호텔의 예
-- 생략
2.1.11. 시스템 호출 unlink
시스템 호출 unlink 는 화일을 시스템으로부터 제거하기 위해 사용된다. 이것은 임시적인 작업화일을 다루는데 유용하다.
int retval;
char *filename;
.
.
retval = unlink(filename);
unlink 는 제거할 화일의 이름을 가진 문자열로 된 한개의 인수만을 가진다.
unlink 는 성공하면 0 을 실패하면 -1 을 돌려준다.
2.1.12. open 호출의 확장된 특징
open 이 부가적인 특징을 제공한다. 부가의 상수 O_APPEND 를 소개한다. 만일 O_APPEND 가 지정되면, 쓰기가 일어날 때마다 화일의 끝에 위치하게 된다. 이것은 프로그래머가 원래의 내용은 그대로 두고 화일의 끝에 자료를 덧붙이기를 원하는 경우에 유용하다.
O_WRONLY 와 O_APPEND 가 기호 '|' (c 의 비트 단위 OR 명령어)에 의해 결합되는 방법에 유의하라.
filedes = open("yetanother", O_WRONLY|O_APPEND);
open 은 creat 와 유사한 방법으로 화일을 생성하거나 화일의 내용을 백지화 하는데 사용 될 수 있다. 세가지 기본 플래그중의 하나와 fcntl.h 에 있는 부가의 플래그 O_CREAT, O_TRUNC, O_EXCL 를 결합함으로써 얻을 수 있다.
fd = open("file", O_WRONLY|O_CREAT|O_APPEND, 0644);
만일 화일의 내용을 백지화하고 싶으면 O_CREAT 와는 별개로 O_TRUNC 를 사용해야 한다.
fd = open("file", O_WRONLY|O_CREAT|O_TRUNC, 0644);
O_EXCL 은 독립적으로 사용될 수 없다. 그러나 O_CREAT 와 함께 지정되면, 화일이 존재할 때는 open 이 실패하게 된다.
fd = open("lock", O_WRONLY|O_CREAT|O_EXCL, 0644);
lock 은 화일이 존재하지 않을 경우는 화일 lock 을 생성하고, 화일이 존재하면 실패(-1을 돌려줌) 하라는 명령이다. 이것은 동시에 여러 프로세스가 같은 화일을 생성할 수 있는 상황에서 우연히 화일이 훼손되는 것을 막기 위한 방법으로 유용하게 사용될 수 있다.
2.1.13. 시스템 호출 fcntl
fcntl 시스템 호출은 이미 열려있는 화일에 대해서 제어를 하기 위해 사용된다. fcntl 은 하나의 잘 정의된 기능을 가진 시스템 호출이 아니라 여러 기능을 수행하는 다소 이상한 시스템 호출이다.
#include <fcntl.h>
/*
*NB: type of 'args' can vary
*/
int status, cmd, filedes, args;
.
.
status = fcntl(filedes, cmd, args);
화일과 프로세스의 상호작용에 관계된 것 F_GETFL 과 F_SETFL 등이 있다. F_GETFL 은 open 에 의해 지정된 현재 화일 상태 플러그(current file status flags) 를 fcntl 이 돌려 주도록 하기 위해 사용된다. F_SETFL 은 화일에 관련된 화일상태 프래그를 다시 지정하기 위해 사용된다.
2.2. 표준 입력, 표준 출력, 표준 오류
2.2.1. 기본개념
UNIX 시스템은 수행중인 프로그램에 대해서 자동적으로 세개의 화일을 개방한다. 그것들은 각각 표준입력, 표준출력, 표준오류라 불리고, 프로그램 안에서 각각 화일 기술어 0, 1, 2 로서 항상 식별된다.
2.2.2. 프로그램 예 io
-- 생략
2.2.3. 표준오류
표준오류는 오류와 경고 메시지를 주기위한 다소 특별한 출력 채널이다.
2.3. I/O 라이브러리 : 미리 살펴보기
표준 I/O 와 시스템 호출 프리미티브 사이의 가장 분명한 차이점은 화일이 기술되는 방법에 있다. 정수형 화일 기술어 대신에 표준 I/O 루틴은 스트림(stream)이라 불리는 객체(entity)를 가지고 작업을 한다. 스트림은 FILE이라 불리는 구조형(structure type)으로 나타낸다.
fprintf 로 오류메시지 출력
printf 는 특정 메시지를 출력하기 위해 사용된다.
#include <stdio.h> /*for stderr definition */
.
.
fprintf(stderr, "error number %d\n",errno);
일관성을 위해 표준오류를 사용하는 명령어나 프로그램에서는 fprintf 를 사용하는 것이 좋다.
2.4. errno 변수와 시스템호출
프로그래머는 C 프로그램안에서 정수형의 extern 변수로 선언하여 errno 를 사용할 수 있다.
extern int errno;
2.4.1. perror 서브루틴
errno 뿐만 아니라 UNIX 는 perror 이라 불리는 루틴(시스템 호출이 아닙)을 제공한다. 이것은 하나의 문자열 인수를 가진다. perror 이 호출되면, 루틴에 전달된 문자열 인수, 콜론, errno 변수의 현재 값에 대응되는 부가의 메시지 등으로 구성되는 메시지를 표준 오류로 출력한다. 오류 메시지를 표준 출력이 아니라 표준오류로 출력하기 때문에 더 유용하다.
perror("error opening nonesuch");
'Academy I > Tech Academy' 카테고리의 다른 글
Unix System Programming 6 (0) | 2014.12.16 |
---|---|
Unix System Programming 5 (0) | 2014.12.16 |
Unix System Programming 4 (0) | 2014.12.16 |
Unix System Programming 3 (0) | 2014.12.16 |
Unix System Programming 1 (0) | 2014.12.16 |
Domain Driven Design - Modeling (0) | 2014.12.15 |
SQL로 하둡 쿼리를 처리하는 방법 10가지 (0) | 2014.12.11 |
Unix 14 Shell Programming의 추가사항 (0) | 2014.12.04 |