开放/读取/写入是否具有缓冲区?

3

我的程序只使用了打开/读取/写入函数,但是oprofile显示:

20537     2.9883  tyn_indexer              tyn_indexer              nodes_term32_flush
11966     1.7411  vmlinux                  vmlinux                  jbd2_journal_commit_transaction
11733     1.7072  vmlinux                  vmlinux                  __strnlen_user
10741     1.5629  vmlinux                  vmlinux                  nobh_truncate_page
9728      1.4155  vmlinux                  vmlinux                  generic_file_buffered_write
9443      1.3740  vmlinux                  vmlinux                  mpage_da_map_and_submit
9023      1.3129  vmlinux                  vmlinux                  do_get_write_access
7283      1.0597  vmlinux                  vmlinux                  invalidate_interrupt31
5894      0.8576  vmlinux                  vmlinux                  write_cache_pages_da
5332      0.7758  vmlinux                  vmlinux                  journal_submit_commit_record
5316      0.7735  vmlinux                  vmlinux                  hugetlbfs_symlink

generic_file_buffered_write是如何实现的,open/read/write函数是否具有缓冲功能?


2
缓冲发生在许多不同的层面。你问的是哪个层面? - William Pursell
{stdin, stdout, stderr}总是被缓冲的。如果你的程序使用fprintf()向stdout或stderr输出,那么输出将会被缓冲。 - wildplasser
我期望open是一个未经缓冲的系统调用,但是generic_file_buffered_write可能被其他东西引入。oprofile命令使用了什么?你的程序是静态链接还是动态链接的?如果你在程序上运行nm命令,你是否看到了generic_file_buffered_write这个名称? - gbulmer
@gbulmer 它是动态链接的,如果使用nm -DC,我看不到generic_file_buffered_write。 - Mickey Shine
1
@wildplasser:stderr并非完全缓冲(可以是行缓冲或无缓冲),但这几乎不重要。程序员不会通过直接调用open、close、read、write来操作任何标准I/O流(尽管流的底层实现肯定使用它们)。 - Jonathan Leffler
显示剩余4条评论
2个回答

5
这取决于你所说的缓冲区是什么。当C程序员说这些函数是未经缓冲的时,它意味着没有一个应用程序进程本地的缓冲区可以防止其他进程以一致的方式查看数据。这些函数在内核中的实现可以自由地进行更多或更少的缓冲,只要以对应用程序进程透明的方式完成就行(即不会干扰其在文件上是否或何时看到数据)。
另一方面,stdio通常是带有缓冲的,这意味着如果你使用stdio(来自的FILE *函数)访问文件,数据可能在你实际想要读取和使用它之前从底层文件描述符中读取并缓存在你进程的内存空间中,而其他进程则无法看到它,或者你已经写入的数据可能仍然缓存在你的进程内存空间中,在长时间内其他进程也无法看到它(除非你调用fflush)。

0

readwrite系统调用具有相当任意的语义,这完全取决于您正在交互的设备。

read函数可以执行各种操作。例如,如果您正在从处于熟模式(“规范输入处理”)的TTY驱动程序中读取,并请求1个字节,则read将不会返回该一个字节,直到实际可用的完整行。但即使在原始模式下,仍然存在缓冲区。数据以中断驱动的方式从键盘或串口接收,即使您的进程没有调用read,也会保存在缓冲区中。

read函数可以丢弃数据。如果您正在从传统的Unix原始磁带设备中读取扇区或从数据报套接字中读取数据报,并且您提供的缓冲区太小而无法容纳整个扇区或数据包,则多余的数据将被截断。

write到文件时,实际上数据写入磁盘之前就可能返回。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接