read()가 getc()보다 느린 이유는 무엇입니까?

read()가 getc()보다 느린 이유는 무엇입니까?

read보다 느립 니까 getc?

예를 들면 다음과 같습니다.

for (;;) {
        chr++;
        amr=read(file1, &wc1, 1);
        amr2=read(file2, &wc2, 1);
        if (wc1 == wc2) {
            if (wc1 == '\n')
                line++;
            if (amr == 0) {
                if (eflg)
                    return (1);
                return (0);
            }
            continue;
        }

그보다 느립니다:

for (;;) {
    chr++;
    c1 = getc(file1);
    c2 = getc(file2);
    if (c1 == c2) {
        if (c1 == '\n')
            line++;
        if (c1 == EOF) {
            if (eflg)
                return (1);
            return (0);
        }
        continue;
    }

getc시스템 호출을 사용하는데 read왜 속도가 느려지나요?

답변1

getc()는 읽기 데이터를 반환하기 전에 버퍼링하기 때문에 를 호출한다고 해서 getc()반드시 가 호출되는 것은 아닙니다 read(). read()커널이 수행할 작업이 더 많기 때문에 일반 함수 호출보다 완료하는 데 훨씬 더 오랜 시간이 걸리는 시스템 호출입니다. 커널 공간에 들어가면 스택을 변경하고, 모든 컨텍스트를 저장하고, 마스크에 대한 중단을 처리하고, 다른 쪽 끝에서는 완료되면 컨텍스트와 중단을 복원하고, 사용자 공간 스택을 다시 넣습니다. 이것이 바로 사용 가능한 버퍼링된 데이터가 있는 경우 중요한 오버헤드를 절약하기 때문에 getc()를 선호하는 이유입니다.

답변2

디스크에서의 읽기는 블록 지향적이라는 사실로 귀결됩니다. 디스크에서 단일 바이트를 읽으려면 하드웨어는 결국 블록(512 또는 1024 또는 일부 수)의 바이트를 읽고 모든 것을 버퍼링하여 커널에 전달하게 됩니다. . 파일의 블록 0에서 파일의 바이트 0을 읽고 몇 가지 작업을 수행한 다음 파일에서 바이트 1을 읽으면 커널은 아마도 파일의 블록 0에서 다시 읽게 될 것입니다. 그리고 다시 바이트 2에 대해, 또 다시 바이트 3에 대해 그렇습니다. 커널과 디스크 드라이브 자체 모두에 잠재적인 캐싱이 있지만 커널은 많은 프로세스를 처리하므로 그렇지 않을 수도 있습니다.

또한 각 read()호출은 CPU를 사용자 상태에서 커널 상태로 변경해야 합니다. 최소한 메모리 매핑은 변경됩니다. 아마도 그다지 명확하지 않은 다른 일들이 많이 일어날 것입니다. 그것도 시간이 걸릴 수 있습니다.

시스템 read()호출은 CPU 상태를 변경하고 디스크 I/O를 수반할 수 있습니다. getc()사용자 공간에서 전체 디스크 블록(또는 그 이상)을 버퍼링할 수 있으므로 512개의 호출로 인해 getc()커널은 단일 상태 변경으로 단일 디스크 블록을 읽게 됩니다. 살펴보면 디스크의 파일에 대한 시스템 호출 또는 효율적인(디스크 블록 다중) 크기로 간주되는 stdio.h상수에 대한 매크로를 찾을 수 있습니다 .BUFSIZread()write()

관련 정보