我读过课本(Unix环境下的高级编程(
本章中描述的函数通常被称为无缓冲I/O,与我们在第5章中所描述的标准I/O例程不同术语unbuffered表示每次读取或写入都会调用内核中的系统调用这些无缓冲的I/O功能不是ISO C的一部分,而是POSIX.1和单一UNIX规范的一部分。
我与混淆了术语unbuffered意味着每次读取或写入都会调用内核中的系统调用
读写功能是
ssize_t read(int fd, void *buf, size_t nbytes);
ssize_t write(int fd, const void *buf, size_t nbytes);
我在他们的参数中找不到任何特别的东西,哪个参数是系统调用?
系统调用成本高昂,因此标准IO库会尽可能推迟调用,例如通过内部缓冲输出。当它不能再缓冲时,它最终调用一个系统调用。
该缓冲区通常与FILE
指针相关联,因此经验法则是采用FILE *
的函数进行缓冲,而采用原始int
文件描述符的函数进行系统调用。这只是一个惯例,不再是了。
Posix命名法试图用f
作为标准IO例程的前缀,例如fwrite
,而原始系统调用是write
(与fopen
和open
等相同(。参数有一点特别,它在一个名称中。
通常,这些是系统调用。可以想象,它们可能只是一个使用其他系统调用来完成工作的正常函数(例如,read
调用一组较小的底层操作(,UNIX及其同类往往是一对一映射的。
但是无缓存I/O的基本思想是没有缓存
当您以无缓冲的方式读取和写入数据时,数据会立即发送到底层或从底层检索(系统调用间接提及(。
相比之下,缓冲方法可以在写入数据之前缓存数据,或者在需要时可以读取比预期更多的数据,这两种方法都可以提高效率。
例如,请参见以下(伪代码(writebuffered
:
def internal buffer size 1024 initially empty
def function writebuffered, accepts data:
for each char in data:
if internal buffer is full:
write internal buffer
empty internal buffer
append char to internal buffer
您可以看到,它只会在内部缓冲区已满时进行系统调用(write
(,从而减少系统调用。显然,在现实生活中,你不会一次处理一个字符,但处理大块的行为会使代码不必要地复杂化。这里的意图只是显示缓冲。
同样,在读取(例如,27个字符(时,系统调用可能会获得更大的量(比如1K(,并将其保存在预读缓冲区中以备以后使用,因为您可能会想要读取更多。
然后,假设稍后的读取小于或等于1K - 27
字节,则不必进行另一个系统调用来获取数据,只需从预读缓冲区中获取即可。