Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Unix中对行缓冲区的误解_C_Unix - Fatal编程技术网

C Unix中对行缓冲区的误解

C Unix中对行缓冲区的误解,c,unix,C,Unix,我正在阅读《UNIX环境中的高级编程》第3版,并误解了其中的一节(第145页,第5章第5.4节缓冲) 行缓冲有两个警告。首先,缓冲区的大小 用于收集每条线的标准I/O库是固定的,因此如果 我们在写换行之前先填充这个缓冲区第二,无论何时输入 通过标准I/O库从(a)无缓冲流或(b)行缓冲流(需要从内核请求数据)中请求, 刷新所有行缓冲输出流。(b)上的限定符的原因 请求的数据可能已经在缓冲区中,这不需要 要从内核读取的数据。显然,来自非缓冲区的任何输入 流(项目(a)要求从内核获取数据。 我看不到

我正在阅读《UNIX环境中的高级编程》第3版,并误解了其中的一节(第145页,第5章第5.4节缓冲)

行缓冲有两个警告。首先,缓冲区的大小 用于收集每条线的标准I/O库是固定的,因此如果 我们在写换行之前先填充这个缓冲区第二,无论何时输入 通过标准I/O库从(a)无缓冲流或(b)行缓冲流(需要从内核请求数据)中请求, 刷新所有行缓冲输出流。(b)上的限定符的原因 请求的数据可能已经在缓冲区中,这不需要 要从内核读取的数据。显然,来自非缓冲区的任何输入 流(项目(a)要求从内核获取数据。


我看不到粗体字。我的英语不好。那么,你能为我澄清一下吗?也许用一种更简单的方式。谢谢。

所述设计背后的要点是确保在系统进入等待输入的模式之前出现提示

如果输入流是无缓冲的,那么每当标准I/O库需要数据时,它都必须到内核获取一些信息。(这是最后一句话。)这是因为标准I/O库不缓冲任何数据,所以当它需要更多数据时,它必须从内核读取。(我认为,即使是未缓冲的流也可能缓冲一个字符的数据,因为它需要最多读取一个空格字符,例如,检测它何时到达
%s
格式字符串的末尾;它必须放回(
ungect()
)它读取的额外字符,以便下次需要一个字符时,有它放回的字符。但它永远不需要超过一个字符的缓冲。)

如果输入流是行缓冲的,那么它的输入缓冲区中可能已经有一些数据,在这种情况下,它可能不需要去内核获取更多数据。在这种情况下,它可能不会冲洗任何东西。如果请求了
scanf()
格式
“%s”
,并且您键入了
hello world
,则可能会发生这种情况;它将读取整行内容,但第一次扫描将在
hello
之后停止,下一次
scanf()
不需要转到内核中查找
world
字,因为它已经在缓冲区中

但是,如果缓冲区中没有任何数据,它必须要求内核读取数据,并确保刷新任何行缓冲输出流,以便在写入时:

printf("Enter name: ");
if (scanf("%63s", name) != 1)
    …handle error or EOF…

然后出现提示(
输入名称:
)。但是,如果您之前键入了
hello world
,并且之前只阅读了
hello
,则不一定会出现提示,因为
world
已经在(行缓冲)输入流中等待。

这可能解释了这一点

让我们假设您的程序中有一个管道,并且您使用它在程序的不同部分之间进行通信(单线程程序从这个管道写入和读取)

如果写入到管道的写入端,请说出字母“A”,然后调用读取操作从管道的读取端读取。你会认为字母“A”是读出来的。然而,读操作是对内核的系统调用。要返回字母“A”,必须先将其写入内核。这意味着必须刷新“A”的写入,否则它将留在本地写入缓冲区中,并且您的程序将永远被锁定


因此,在调用读取操作之前,将刷新所有写入缓冲区。这就是(b)部分所说的。

标准I/O库用于收集每行数据的缓冲区大小是固定的

在fgets函数的帮助下,我们将连续获取行,在此期间,它将以指定的缓冲区大小或最大换行数读取内容

其次,无论何时通过标准I/O库请求输入,它都可以使用无缓冲流或行缓冲流。

无缓冲流-它不会缓冲字符,定期刷新字符

行缓冲-它将字符存储到缓冲区中,然后在操作完成时刷新

让我们不使用
\n
而使用printf语句打印内容,此时它将缓冲所有内容,直到刷新或使用新行打印。与此类似,当操作完成时,将在内部刷新流缓冲区

(b)是指请求的数据可能已经在缓冲区中,不需要从内核读取数据

在面向行的流中,请求的缓冲区可能已经在缓冲区中,因为数据可以被缓冲,所以我们不能要求再次从内核读取数据

(a)要求从内核获取数据。


来自未缓冲流项的任何输入,由于未缓冲流而从内核获取的数据不能在缓冲区中存储任何内容。

当执行
printf
时,字符串将存储在缓冲区中(尚未在终端上显示)
scanf
然后将从作为行缓冲流的stdin请求数据。如果stdin缓冲区为空,
scanf
将要求内核读取数据,内核将刷新程序中任何当前行缓冲的输出流(包括文件流、套接字流等,如果有)。结果是字符串将显示在终端上。否则,如果
stdin
缓冲区已经有数据,
scanf
将获取该数据,而不要求内核读取数据。因此,除非随后刷新缓冲区,否则字符串可能不会显示。我误解了什么吗?@Phieu:内核不知道b行