Library
- 재사용 할 수 있도록 function을 저장해둔 set
- 보통 Linux에는 /lib나 /usr/lib에 위치한다.
- 필요한 함수가 user program과 link된다.
Library 종류
1) Static Library (*.a)
- binary program에 직접적으로 연결
- 모든 program에 각각 연결되어 있는 방식
- 주로 embedded system에서 사용한다.
2) Shared Library (* .so, *.dll)
- 공용으로 사용하는 library
- memory의 낭비를 줄일 수 있다.
- 'OS'의 도움을 받아서 library로 가는 길을 찾는다.
- 주로 server system에서 사용한다.
Standard I/O Library
- <stdio.h> : standard I/O library를 정의한 헤더파일
- special files → streams → OS에 의해 시작될 때 자동으로 생성
- stdin, stdout, stderr
왜 standard I/O Library를 사용하는가?
- OS를 통하지 않고는 system call을 할 수 없기 때문
- formatting, buffering을 사용하기 위해
File Descriptor
- OS가 접근할 때 사용하는 것
- File Descriptor Table에 정수로 저장되어 있다.
- 0, 1, 2는 각각 stdin, stdout, stderr로 고정되어 있다.
- 새로운 file이 열리면 3번부터 차례로 부여된다.
Library Buffering
- buffer : 데이터를 임시 저장할 수 있는 메모리 공간
- file pointer object를 이용하여 file을 open해서 data를 write하기 전에 임시 저장을 할 수 있는 공간을 마련하고, 그 공간에 저장한 다음 한번에 write하는 방식.
- system call의 횟수를 줄인다.
### Buffering 방식
1) Full Buffering
- buffer가 가득 찼을 때만 read/write가 가능
- system call을 매우 줄일 수 있다.
- data를 내보내기 힘들다는 단점이 존재
- fflush()를 이용하여 강제로 data를 내보낼 수 있다.
- 대부분의 library buffering 방식
2) Line Buffering
- Console I/O에 사용된다.
- 줄바꿈(enter 키)이 생겼을 때 동작한다.
- stdin, stdout이 해당된다.
3) UnBuffering
- library buffer를 사용하지 않는다.
- system call을 바로 전달하기 때문에 성능이 나쁘다.
- 전원이 갑자기 꺼지는 경우와 같을 때 좋다.
- stderr가 해당된다.
Set Buffering Type
#include <stdio.h>
void setbuf(FILE *stream, char *buf);
// return : None
int setvbuf(FILE *stream, char *buf, int type, size_t size);
// return 0 for success, or nonzero for an error
Kernel Buffering
- user buffer와 별개로 OS 내의 kernel도 data를 모아서 처리하도록 구성한다.
- disk에 접근을 최소화한다.
- OS는 disk에서 block 단위로 data를 읽어온다.
- buffer cache : buffer는 한 방향으로 모아서 보내지만, cache는 중간 매개체 역할을 한다.
I/O buffering & Sync
#include <stdio.h>
int fflush(FILE *stream);
// return 0 for normal, EOF for error
- buffer가 가득 차지 않아도 library buffer에 있는 것을 kernel로 block 단위만큼 내려준다.
- kernel까지 내려주지만, sync()를 호출하면 disk까지 간다.
File Open/Reopen
1) fopen
FILE *fopen(const char *filename, const char *type);
- type : access mode
- return : 성공 시 열린 file의 file pointer / 실패 시 NULL
- open file의 개수는 제한이 되어 있다.
2) freopen
File *freopen(const char *filename, const char *type, FILE *stream);
- type : access mode
- stream : file pointer
- return : 성공 시 열린 file의 file pointer / 실패 시 NULL
- 이전 stream을 그대로 사용하기 때문에 File 이름하고의 관계만 끊어진다.
File Close
int fclose(FILE *stream);
- open 된 file을 닫는다.
- process가 종료되면 OS가 file descriptor table을 보고 모든 file을 자동적으로 닫는다.
File I/O Functions
size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream)
- ptr: buffer 주소
- size: object의 byte수 (전체 size)
- nitems: object의 수
- stream: file pointer
- return : 성공 시 읽은 object의 수 / 실패 시 0
size_t fwrite(void *ptr, size_t size, size_t nitems, FILE *stream)
- ptr: buffer 주소
- size: object의 byte수 (전체 size)
- nitems: object의 수
- stream: file pointer
- return : 성공 시 쓴 object의 수 / 실패 시 0
int getc(FILE *stream)
int fgetc(FILE *stream)
- file에 char를 가져온다.
- return : 성공 시 int type의 char / 실패 시 EOF
int getchar(void)
- stdin으로부터 char를 가져온다.
- return : 성공 시 int type의 char / 실패 시 EOF
char *fgets(char *s, int size, FILE *stream)
- NULL("\O")이 나올 때(줄바꿈)까지 문자열을 가져온다.
- size : max string size + 1
- return : 성공 시 string의 address / 실패 시 NULL
char *gets(char *s)
- stdin에서 NULL("\O")이 나올 때(줄바꿈)까지 문자열을 가져온다.
- return : 성공 시 string의 address / 실패 시 NULL
Character Output
int putc(int c, FILE *stream),
int fputc(int c, FILE *stream)
- file에 char를 write한다.
- return : 성공 시 int type의 char / 실패 시 EOF
int putchar(int c)
- stdout에 char를 write 한다.
- return : 성공 시 int type의 char / 실패 시 EOF
int *fputs(const char *s, FILE *stream)
- NULL("\O")이 나올 때(줄바꿈)까지 문자열을 write한다.
- return : 성공 시 char의 수 / 실패 시 EOF
char *puts(const char *s)
- stdout에 NULL("\O")이 나올 때(줄바꿈)까지 문자열을 write한다.
- return : 성공 시 char의 수 / 실패 시 EOF
File Offset
- 모든 open file은 file에서 다음 접근 위치를 나타내는 r/w offset을 가진다.
- read/write는 현재 offset이 위치한 곳에서 일어난다.
- file이 처음 read/write를 위해 open될 때, offset은 file의 처음에 위치한다.
- file이 추가를 위해 open 될 때, offset은 file의 끝에 위치한다.
- read/write가 진행되는 동안, offset은 자동적으로 최신화된다.
File Access
1) Sequential Access (순차접근)
- 현재 r/w offset에 따라 접근한 뒤 read/write를 진행한다.
2) Random Access
- 원하는 위치에 r/w offset을 이동시킨 후 read/write를 진행한다.
- 주로 fseek(), lseek()를 사용한다.
- fseek() : Library function
- lseek() : System Call
R/W offset function
int fseek(FILE *stream, long offset, int sopt)]
- offset을 지정된 위치로 이동
- stream : file pointer
- offset : SEEK option에서 떨어진 거리
- sopt : SEEK option
- return : 성공 시 0 / 실패 시 -1
SEEK option
- SEEK_SET : new r/w offset = offset
- SEEK_CUR : new r/w offset = current_offset+ offset
- SEEK_END : new r/w offset = EOF+ offset
void rewind(FILE *stream)
long ftell(FILE *stream)
- offset의 현재 위치를 return
- return : 성공 시 현재 offset / 실패 시 -1
I/O Types
- 자료형 그 자체를 그대로 저장하거나 읽는 것
- program만 이해가 가능하다.
- integer, float, double...
2) Formatted I/O(Text I/O)
- ASCII 코드 등으로 해석해주는 것
- 다른 program은 필요 없지만 data 양이 많아진다.
- %f, %5d, cat file...
int printf(const char *format,/* args*/ ... )
- console에 출력
- return : 성공 시 output length / 실패 시 negative integer
int fprintf(FILE *stream, const char *format,/* args*/ ... )
- file에 출력
- return : 성공 시 output length / 실패 시 negative integer
int sprintf(char *s, const char *format,/* args*/ ... )
- char buf 에 출력
- return : 성공 시 output length / 실패 시 negative integer
int scanf(const char *format,... )
- console에 입력한 것을 읽어들임
- return : 성공 시 input length / 실패 시 EOF
int fscanf(FILE *stream, const char *format,... )
- file에 입력한 것을 읽어들임
- return : 성공 시 input length / 실패 시 EOF integer
int sscanf(char *s, const char *format,... )
- char buf 안에 있는 것을 읽어들임
- return : 성공 시 input length / 실패 시 EOF integer
Error Handling
- 특정 파일에 여러가지 error가 발생 가능하다.
- error number에 따라 다르게 정의되어 있다.
- <errno.h> 에 정의된 errno 변수를 통해 알 수 있다.
File error check
int ferror(FILE *stream)
- error가 발생했을 때 return을 확인
- return : error가 있으면 errno / error가 없으면 0
int feof(FILE *stream)
- file의 끝에 도달하였는지 판단
- return : file의 끝에 도달하지 않았으면 errno / 도달했으면 0
void clearerr(FILE *stream)
- 현재까지 발생한 error를 clear해준다.
- 가능하면 사용하지 않는 것이 좋다.