-
[시스템프로그래밍] Standard I/O Library개발 이야기/운영체제(OS)&시스템프로그래밍 2024. 10. 21. 04:00
본 내용은 한양대학교 조인휘 교수님의 시스템 프로그래밍 강의 자료를 기반으로 작성되었습니다
Standard I/O Library
Standard I/O Library(표준 입출력 라이브러리)는 C 프로그래밍 언어에서 파일 및 콘솔 입출력 작업을 쉽게 처리할 수 있도록 제공되는 표준 함수들의 집합이다. 이들은 Buffer를 이용하고 시스템 레벨의 파일 입출력보다 고수준의 기능을 제공한다.
ISO C standard를 따른다.
Stream
표준 스트림이란 컴퓨터 프로그램과 그 환경(단말기) 사이에 미리 연결된 입출력 통로를 의미한다.
Buffering
버퍼링은 UNIX Overview에서 작성한 것과 같이 입출력 성능을 위해 데이터를 바로바로 처리하지 않고 임시 저장소에 쌓아 두었다가 한번에 처리하는 방식이다. 이를 통해 시스템 호출을 최소화하고 성능을 개선하려고 한다. 3종류로 구분된다.
- Fully Buffered
버퍼가 꽉 찼을 때만 데이터를 입출력하는 방식이다. 버퍼가 가득 차기 전까지는 버퍼에 데이터를 저장하고, 버퍼가 꽉 차면 그때 한 번에 출력하거나 파일에 기록하는 방식이다. 일반적으로 파일 입출력에서 사용한다.
- Line Buffered
줄 버퍼링은 개행 문자(\n)를 만나거나 버퍼가 꽉 찰 때 데이터를 입출력하는 방식이다. 출력하는 데이터가 줄바꿈 문자(\n)를 포함하면 버퍼에 있는 데이터를 즉시 처리하여 출력한다.
- Unbuffered
데이터를 즉시 처리하는 방식으로 즉각적으로 입출력 작업을 수행한다. 실시간 데이터 처리가 필요한 경우 사용한다.
setbuf, setvbuf
#include <stdio.h> void setbuf(FILE *fp, char *buf); int setvbuf(FILE *fp, char *buf, int mode, size_t size);
buffering을 enable하거나 disable할 때 사용한다.
setbuf와 setvbuf의 차이는 mode 설정의 유무이며 mode는 _IOFBF, _IOLBF, _IONBF가 있으며 이는 위에서 언급한 Fully Buffered, Line Buffered, Unbuffer에 해당한다.
fflushed()
#include <stdio.h> int fflush(FILE *fp);
flush는 비우다는 뜻으로 fflush()는 c표준 입출력 라이브러리에서 출력 스트림에 있는 버퍼의 데이터를 강제로 비워 즉시 출력하거나 기록하는데 사용한다. 즉, 명시적으로 디스크나 콘솔에 쓰도록 강제하거나 초기화하는 용도로 사용가능하다.
fopen(), freopen(), fdopen()
#include <stdio.h> FILE *fopen(const char *pathname, const char *type); FILE *freopen(const char *pathname, const char *type, FILE *fp); FILE *fdopen(int filedes, const char *type);
fopen()은 파일을 열어 읽기 또는 쓰기 스트림을 제공, 새로 파일 스트림을 생성한다
freopen()은 기존에 열려있는 스트림을 닫고 해당 스트림을 새파일과 연결한다(atomic 보장), 즉 표준 입력 또는 출력을 특정 파일로 재지정한다.
open과 fopen비교:
open(): 저수준 파일 입출력을 위해 사용되는 POSIX 시스템 호출로, 파일 디스크립터를 반환합니다. 파일을 열고, 직접 읽고 쓰는 작업에 사용되며, 버퍼링이 제공되지 않으므로 성능 최적화를 위해 직접 관리해야 합니다.
fopen(): C 표준 라이브러리 함수로, 고수준 파일 입출력을 제공합니다. FILE 포인터를 반환하며, 버퍼링을 통해 성능이 자동으로 최적화됩니다. 표준 입출력 함수를 사용할 수 있어 코드가 더 간결하고 이식성이 높습니다.fdopen은 pipe나 network에 주로 사용한다.
fclose()
#include <stdio.h> int fclose(FILE *fp);
파일을 닫는다. 이때 파일을 닫을 때, 열린 파일에 대한 모든 버퍼링된 데이터를 파일에 기록하고, 파일에 할당된 자원을 해제한다.
getc fgetc getchar: 문자를 입력받자
#include <stdio.h> int getc(FILE *fp); int fgetc(FILE *fp); int getchar(void);
파일이나 표준 입력(키보드)에서 한 번에 한 문자씩 읽어오는 역할을한다.
getc()와 fgetc() 모두 파일 스트림에서 한 문자씩 읽어온다.
getc()와 fget()의 차이는 getc는 macro 즉 # dfine되어 있어 빠르고, fgetc()는 표준함수로 구현되어있어 모든 구현에서 일관된 동작을 보장한다.
getchar() == getc(stdin)로 표준 입력에서 한 문자를 읽어온다.
ferror feof clarerr
#include <stdio.h> int ferror(FILE *fp); int feof(FILE *fp); void clearerr(FILE *fp); /* clear both flags */
파일 입출력 작업 시 발생할 수 있는 오류 상태나 파일 끝(EOF) 상태를 확인학 위해 사용. 파일 스트림에서 입출력이 성공적으로 이루어졌는지 확인하기 위해 사용된다.
ferror() 함수는 파일 스트림에서 오류가 발생했는지를 확인하는 함수이다.
feof() 함수는 파일 스트림이 EOF(파일 끝) 상태에 있는지를 확인하는 함수이다.
clearerr() 함수는 파일 스트림의 오류 플래그와 EOF(파일 끝) 플래그를 **초기화(재설정)**하는 함수. 파일 스트림에서 오류가 발생하거나 파일 끝에 도달한 경우, 이를 해제하고 다시 입출력 작업을 시도할 수 있도록 상태를 초기화한다.
ungetc
#include <stdio.h> int ungetc(int c, FILE *fp);
입력 스트림으로부터 읽은 문자를 다시 입력 버퍼에 돌려주는 함수이다. 즉, 이미 읽은 문자를 다시 스트림으로 되돌려 놓아서, 다음 번 입력에서 이 문자를 다시 읽을 수 있도록 한다.
putc fputc putchar
#include <stdio.h> int putc(int c, FILE *fp); int fputc(int c, FILE *fp); int putchar(int c);
C 표준 라이브러리에서 한 문자를 출력하는 함수들이다. 이 함수들은 파일 스트림 또는 표준 출력 스트림에 한 문자씩 데이터를 출력하는 용도로 사용된다.
putc는 매크로로 구현되어있으며 빠르게 작동한다.
fputc는 표준 입출력 함수로 일관된 동작을 보장한다.
putchar의 경우 파일 스트림을 사용하지 않고 화면에 출력하는 데 사용되며, 내부적으로는 putc(c, stdout)과 동일하게 동작한다.
fread, fwirte(): ISO standard로 버퍼로 데이터를 읽고 쓰자
#include <stdio.h> size_t fread(void *ptr, size_t size, size_t nobj, FILE *fp); size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *fp);
이진 데이터 또는 버퍼로 데이터를 읽고 쓸 때 사용됩니다. 이 함수들은 데이터를 블록 단위로 처리하며, 텍스트 파일뿐만 아니라 바이너리 파일을 다룰때 유용하다.
fread()는 파일에서 데이터를 읽어와 버퍼에 저장하는 함수이다. 데이터의 크기와 개수를 지정하여 여러 바이트를 한 번에 읽을 수 있다.
fwrite()는 버퍼에 있는 데이터를 파일에 기록하는 함수로. 역시 데이터의 크기와 개수를 지정하여 데이터를 쓸 수 있다.ftell fseek rewind: 파일의 위치 제어, 파일 포인터의 위치 확인 or 이동 & ftello fseeko: 대용량용
#include <stdio.h> long ftell(FILE *fp); int fseek(FILE *fp, long offset, int whence); void rewind(FILE *fp);
ftell() 함수는 파일 포인터의 현재 위치를 파일 시작 지점으로부터의 오프셋(바이트 단위)로 반환
fseek() 함수는 파일 포인터를 특정 위치로 이동시키는 함수
rewind() 함수는 파일 포인터를 파일의 처음으로 되돌리는 함수, 오류 플래그와 EOF 플래그도 초기화한다.
뒤에 o가 붙은 두 함수는 대용량 파일을 위해 만들어진 함수이다.
fgetpos, fsetpos: 파일의 현재 위치를 저장/ 복원
#include <stdio.h> int fgetpos(FILE *fp, fpos_t *pos) int fsetpos(FILE *fp, const fpos_t *pos);
fgetpos() 함수는 파일 포인터의 현재 위치를 저장하는 함수이다. 현재 파일에서 읽거나 쓰고 있는 위치를 fpos_t 자료형 변수에 저장한다.
fsetpos() 함수는 이전에 저장된 파일 포인터의 위치로 돌아가는 함수이다.
fileno(): file 디스크립터 반환
int fileno(FILE *stream);
파일 디스크립터는 저수준 시스템 호출에서 사용되며, 파일 스트림을 시스템 호출과 함께 사용할 수 있게 해줍니다. 즉, 고수준 파일 스트림을 저수준 파일 디스크립터로 변환하여 POSIX 시스템 호출(예: read(), write(), close())과 함께 사용할 수 있게 합니다.
Temporary file: *tmpnam *tmpfile tempnam mkstemp
임시파일의 경우 문자 그대로 임시적으로 저장할 파일을 만드는데 유용하며 저장하지 않아도 될 때 사용한다.
우선 tmpnam과 tmpfile은 각각 고유한 임시파일을 생성할 때 사용한다. 이때, tmpnam은 임시파일명을 생성한다, tmpfile은 파일명과 함께 파일을 생성한다. 프로세스 종료시 자동으로 해당파일을 삭제한다.
#include <stdio.h> char *tmpnam(char *ptr); FILE *tmpfile(void);
tempnam은 지정한 디렉터리에 임시파일명을 생성하고, mkstemp는 템플릿을 기반으로 파일명을 생성한다.
#include <stdio.h> char *tempnam(const char *directory, const char *prefix); #include <stdio.h> char *tempnam(const char *directory, const char *prefix);
'개발 이야기 > 운영체제(OS)&시스템프로그래밍' 카테고리의 다른 글
[시스템 프로그래밍] Files and Directories / 권한에 관해 (2) 2024.10.21 [시스템 프로그래밍] File I/O (0) 2024.10.21 [시스템프로그래밍] UNIX System Overview (1) 2024.10.20