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

问题描述

我有一个简单的C文件,该文件使用printfwrite(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

解决方法

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

fsyncwrite在Unix文件描述符1上运行。fsync从文件描述符1中清除数据,但对C标准库流的缓冲区没有影响。

C标准库I / O例程的运行方式有所不同,具体取决于标准输出是发送到终端还是文件。在程序启动过程中将检测到该错误。当输出将输出到终端时,将其传递给用户被认为是很重要的,并且在将\n写入流时,将刷新缓冲区。这称为行缓冲,默认情况下,输出到终端的行设置为行缓冲。

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

这通常在C 2018 7.21.3中得到解决,其中第7段说:

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

(当输出是终端时,C实现也可以使用 unbuffered 模式代替 line buffered ,在这种情况下,所有字符都将尽快发送到终端就像他们写的那样。这是不常见的。)

您可以显式请求使用stdout刷新fflush(stdout)

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

,

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

您可以将stdoutput / input重定向到文件

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...