linux stdin buffer mode是如何工作的?

tf7tbtn2  于 2024-01-06  发布在  Linux
关注(0)|答案(1)|浏览(339)

我知道stdoutbuffer模式是如何工作的,即:

unbuffered:无缓冲。
line buffered:当遇到换行符时刷新buffer。
block buffered:当缓冲区满时刷新。

我能理解上面的内容。
但是我对stdin缓冲区的工作原理感到困惑,我无法想象当使用三种缓冲区模式之一时会发生什么。
对于三个缓冲区模式,什么时候stdin使用哪种模式?
先谢了。

  1. // test02.c
  2. int main(int argc, char *argv[]){
  3. char ptr[20];
  4. scanf("%s",ptr);
  5. printf("%s\n",ptr);
  6. return 0;
  7. }
  8. //./test02 < log
  9. // in this case,scanf() just read the first line of log file
  10. // can anyone explain how the stdin buffer works?

字符串

ztyzrc3y

ztyzrc3y1#

这取决于实现--FILE I/O是如何实现的--这些模式做什么,也包括标准输出。没有任何地方 * 保证 * 设置line buffered实际上会被line buffered。
当在Linux上使用glibc时,当使用普通文件时,下溢读取数据时,读取_IO_new_file_underflow在这里被称为https://github.com/lattera/glibc/blob/895ef79e04a953cac1493863bcae29ad85657ee1/libio/fileops.c#L524 _IO_SYSREAD (fp, fp->_IO_buf_base, fp->_IO_buf_end - fp->_IO_buf_base);。它执行单个read系统调用。你可以按照setbuf来设置缓冲区。
然而,实际的答案要有趣得多。考虑下面的C程序,根据第一个参数,这是一个数字1,2或3,使用全缓冲,行缓冲或无缓冲的标准输入流。

  1. #include <assert.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. int main(int argc, char *argv[]) {
  5. assert(argc >= 1);
  6. const int arg = atoi(argv[1]);
  7. const int mode = arg == 1 ? _IOFBF : arg == 2 ? _IOLBF : _IONBF;
  8. printf("Using mode=%d\n", mode);
  9. char buf[10];
  10. setvbuf(stdin, buf, mode, sizeof(buf));
  11. char ptr[20];
  12. scanf("%19s", ptr);
  13. }

字符串
下面的Makefile编译程序并在strace下运行程序,使用bash here字符串输入两行。这样我们就可以看到正在进行的read系统调用:

  1. SHELL = bash
  2. all:
  3. gcc main.c
  4. strace -e read ./a.out 1 <<<$$'abc\ndef'
  5. strace -e read ./a.out 2 <<<$$'abc\ndef'
  6. strace -e read ./a.out 3 <<<$$'abc\ndef'


在以下方面取得成果:

  1. $ make
  2. gcc main.c
  3. strace -e read ./a.out 1 <<<$'abc\ndef'
  4. read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220~\2\0\0\0\0\0"..., 832) = 832
  5. Using mode=0
  6. read(0, "abc\ndef\n", 10) = 8
  7. +++ exited with 0 +++
  8. strace -e read ./a.out 2 <<<$'abc\ndef'
  9. read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220~\2\0\0\0\0\0"..., 832) = 832
  10. Using mode=1
  11. read(0, "abc\ndef\n", 10) = 8
  12. +++ exited with 0 +++
  13. strace -e read ./a.out 3 <<<$'abc\ndef'
  14. read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220~\2\0\0\0\0\0"..., 832) = 832
  15. Using mode=2
  16. read(0, "a", 1) = 1
  17. read(0, "b", 1) = 1
  18. read(0, "c", 1) = 1
  19. read(0, "\n", 1) = 1
  20. +++ exited with 0 +++


设置_IOFBF_IOLBF只会使用缓冲区10的大小执行一个read()。这两个在阅读时工作相同。但是,_IONBF会执行一个小的read(0, .., 1),直到一个换行符。

展开查看全部

相关问题