-
C/C++ setbuf(3) setvbuf(3)C,C++ & Linux 2020. 5. 21. 10:14728x90
함수 기능
파일의 버퍼를 바꿔주는 함수입니다.
버퍼 방식
버퍼 방식 매크로 설명 Full buffer _IOFBF 버퍼가 가득 차야 파일에 읽고 쓰는 방식으로 주로 일반 파일에 적용 Line buffer _IOLBF 버퍼에 개행 문자가 들어오면 파일에 읽고 쓰는 방식으로 표준 입출력 파일에 쓰임 None buffer _IONBF 버퍼를 사용하지 않고 바로바로 파일에 읽고 쓰는 방식으로 표준 에러 파일에 쓰임 setbuf() 의 경우 buf 인자에 NULL을 넣게 되면 None buffer를 의미하며 NULL이 아닌 값을 넣게 되면 해당 버퍼를 Full buffer 로 사용하게 됩니다. 단 fp 인자가 터미널인 경우 Line buffer 를 사용하게 됩니다. 이때 버퍼의 크기는 BUFSIZ 로 사용되며 이 크기는 시스템마다 다릅니다.
setvbuf() 는 setbuf() 와는 달리 버퍼의 크기와 그 모드를 지정할 수 있습니다.
buf 인자에 NULL을 넣게 되면 None buffer를 사용하게 되며 이때 mode와 size 는 무시됩니다.
NULL이 아닌 값을 넣게 되면 해당 버퍼를 지정된 mode 로 사용하게 됩니다.
mode의 인자로는 _IOFBF, _IOLBF, _IONBF 가 있습니다.
함수 원형
#include <stdio.h> void setbuf(FILE *fp, char *buf); int setvbuf(FILE *fp, char *buf, int mode, size_t size);
매개변수
fp
버퍼를 설정할 파일 포인터
buf
버퍼로 사용할 배열 공간 주소
mode
버퍼 모드
_IOFBF, _IOLBF, _IONBF 사용 가능
size
버퍼의 크기, 기본은 BUFSIZ
반환값
성공 시 0 리턴
에러 시 0이 아닌 값 리턴하고 errno 설정
예제
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char *argv[]) { char buf[BUFSIZ]; // stdout 같은 터미널은 Line buffer 로 지정됨 // 따라서 \n 문자를 만날때 화면에 출력됨 setbuf(stdout, buf); // 출력 x printf("Hello, "); sleep(1); // 출력 x printf("OSLAB!!"); sleep(1); // Hello, OSLAB!!\n 한 번에 출력 printf("\n"); sleep(1); // None buffer 로 변경 // 여기서부터는 매 라인마다 바로바로 출력됨 setbuf(stdout, NULL); // How 출력 printf("How"); sleep(1); // are 출력 printf(" are"); sleep(1); // you? 출력 printf(" you?"); sleep(1); // \n 출력 printf("\n"); exit(0); }
결과
예제2
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char *argv[]) { char buf[BUFSIZ]; int a, b; // buf 를 표준 입력의 버퍼로 지정 // 터미널이므로 Line buffer 로 설정됨 setbuf(stdin, buf); scanf("%d %d", &a, &b); // 새로운 버퍼로 지정된 buf를 출력 for (int i = 0; buf[i] != '\n'; i++) putchar(buf[i]); putchar('\n'); exit(0); }
결과
예제3
#include <stdio.h> #include <stdlib.h> #include <unistd.h> void ssu_setbuf(FILE *fp, char *buf) { size_t size; int fd; int mode; // 파일 포인터로부터 파일 디스크립터를 뽑아내는 함수 fd = fileno(fp); // 터미널인지 확인해주는 함수 if (isatty(fd)) // 터미널인 경우 라인 버퍼 mode = _IOLBF; else // 아닌 경우 풀 버퍼 mode = _IOFBF; // buf 인자가 널인 경우 if (buf == NULL) { // 넌 버퍼 모드 mode = _IONBF; size = 0; } else size = BUFSIZ; // 버퍼 설정 setvbuf(fp, buf, mode, size); } int main(int argc, char *argv[]) { char buf[BUFSIZ]; FILE *fp; // argv[1] 에 다른 터미널의 터미널 파일 아이디를 넣을 것입니다. if ((fp = fopen(argv[1], "w")) == NULL) { fprintf(stderr, "file open error\n"); exit(1); } // 따라서 setbuf 를 하면 isatty 에서 true로 판명되고, line buffer 로 설정됩니다. ssu_setbuf(fp, buf); fprintf(fp, "Hello, "); sleep(1); fprintf(fp, "UNIX!!"); sleep(1); // line buffer 이기 때문에 3초 대기 후 Hello, UNIX!!\n가 한번에 출력 fprintf(fp, "\n"); sleep(1); // None buffer로 교체 ssu_setbuf(fp, NULL); // None 버퍼기 때문에 대기 없이 바로바로 출력 fprintf(fp, "HOW"); sleep(1); fprintf(fp, " ARE"); sleep(1); fprintf(fp, " YOU?"); sleep(1); fprintf(fp, "\n"); sleep(1); exit(0); }
결과
실습 시 두 개의 터미널이 필요합니다.
한 터미널에서 tty 명령어를 통해 어떤 터미널 파일을 쓰고 있는지 확인합니다,
저의 경우에는 /dev/ttys002 가 되겠습니다.
./a.out <본인 터미널 파일> 입력하시면 위 터미널에 Hello, UNIX!!와 HOW ARE YOU? 가 주입됩니다.
리눅스시스템프로그래밍 저자 : 홍지만
https://book.naver.com/bookdb/book_detail.nhn?bid=14623672
책에 기술된 예제 프로그램입니다. 책 내부에는 훨씬 더 많은 자료가 있습니다. (개인적으로 좋았습니다.)'C,C++ & Linux' 카테고리의 다른 글
C/C++ getc(3) fgetc(3) getchar(3) (0) 2020.05.21 C/C++ fflush(3) (0) 2020.05.21 C/C++ fclose(3) fcloseall(3) (0) 2020.05.21 C/C++ fopen(3) freopen(3) fdopen(3) (0) 2020.05.21 C/C++ getcwd(2) get_current_dir_name(2) (0) 2020.05.21