为什么 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您会发现一个常量宏,该常量应该是对磁盘上文件或系统调用的BUFSIZ有效(磁盘块倍数)大小。read()write()

相关内容