重定向操作将订单输出写入文件

问题描述 投票:0回答:2

我有一个简单的 C 文件,它使用

printf
write(1,..)
函数写入标准输出。

文件:main.c

#include<stdio.h>
#include<unistd.h>

int main()
{
    printf("Hello\n");
    printf("Mars\n");
    fsync(1);
    write(1,"Ola\n",4);
    write(1,"Earth\n",6);
}

> gcc main.c -o test

当我将输出重定向到文件时,我看到的顺序与终端中的输出不同。看起来,当我使用重定向时

write(..)
printf(..)
更早写入,甚至很难,
printf()
在代码中更早,并且中间有一个
fsync(..)

是否有一些重定向运算符的变体可以确保顺序,或者我做错了什么。

终端输出:

> ./test

Hello
Mars
Ola
Earth

输出到

out
文件:

> ./test >out
# or ./test|tee out

> cat out

Ola
Earth
Hello
Mars
c linux gcc xterm
2个回答
4
投票

printf
写入C流
stdout
,由C标准库例程缓冲并最终写入Unix文件描述符1。

fsync
write
对 Unix 文件描述符 1 进行操作。
fsync
刷新文件描述符 1 中的数据,但对 C 标准库流的缓冲区没有影响。

C 标准库 I/O 例程的操作方式有所不同,具体取决于标准输出是发送到终端还是发送到文件。这是在程序启动期间检测到的。当输出发送到终端时,将其发送给用户被认为很重要,并且当将

\n
写入流时,缓冲区将被刷新。这称为 line buffered,默认情况下,到终端的输出设置为 line buffered。

当输出进入文件时,及时刷新它并不重要,因为用户不会立即看到它,并且如果输出完全缓冲,性能会更好。因此,仅当缓冲区已满、流关闭或发出显式刷新请求时才会刷新缓冲区。这称为完全缓冲,默认情况下将输出设置为完全缓冲。

这在 C 2018 7.21.3 中得到了普遍解决,其中第 7 段说:

…当且仅当可以确定该流不引用交互设备时,标准输入和标准输出流才被完全缓冲。

(当输出是终端时,C 实现也可以使用 unbuffered 模式而不是 line buffered,在这种情况下,所有字符在写入后都会立即发送到终端。这是不常见的。)

您可以使用

stdout
明确请求刷新
fflush(stdout)

stdout
打开之后但在对其执行任何其他操作之前,您可以使用
setvbuf(stdout, NULL, mode, 0)
更改其缓冲方法,其中
mode
_IOFBF
_IOLBF
_IONBF
(表示全、行、或分别没有缓冲。 (您还可以传递
char
数组及其大小来代替
NULL
0
,库将使用该数组作为缓冲区,之后您不应将该数组用于任何其他目的。如果您传递
NULL
和大小,库可以使用该大小来执行自己的缓冲区分配,但这并不能保证。)
setvbuf
返回一个
int
,如果它无法满足请求,则该值可能为非零。


-1
投票

看看 dup2 系统调用:https://www.geeksforgeeks.org/dup-dup2-linux-system-call/

您可以将标准输出/输入重定向到文件

© www.soinside.com 2019 - 2024. All rights reserved.