ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • C/C++ setbuf(3) setvbuf(3)
    C,C++ & Linux 2020. 5. 21. 10:14
    728x90

    함수 기능

    파일의 버퍼를 바꿔주는 함수입니다.

     

    버퍼 방식

    버퍼 방식 매크로 설명
    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

    댓글

Designed by Tistory.