首页 > 运维 > linux运维 > 正文

初识Linux · 重定向和缓冲区(续)

絕刀狂花
发布: 2025-06-20 11:14:01
原创
877人浏览过

本文是关于重定向和缓冲区的延续篇,内容较为简短。本文的重点在于介绍stderr,深化对缓冲区和重定向的理解。

让我们直接进入主题。

为了加深对缓冲区的理解,我们将通过C语言中的sprintf函数进行讲解。sprintf函数虽然在C语言中较少使用,但学习Linux的过程中会涉及到C语言底层函数的调用。

初识Linux · 重定向和缓冲区(续)sprintf函数的参数与printf类似,首参数为字符串,后面是普通的printf参数。

我们可以使用该函数将数据写入数组中:

int main(){    
    myFILE *fp = my_fopen(FILE_NAME, "w");    
    if(fp == NULL) return 1;    
    const char *str = "hello bit";    
    int cnt = 10;    
    char buffer[128];    
    while(cnt)    
    {        
        sprintf(buffer, "%s - %d", str, cnt);        
        my_fwrite(fp, buffer, strlen(buffer)); // 不需要strlen()+1        
        cnt--;        
        sleep(1);        
        my_fflush(fp);    
    }    
    my_fclose(fp);    
    return 0;
}
登录后复制

通过sprintf写入数据后,使用我们自己实现的fwrite函数将数据写入fp文件指针指向的缓冲区。每写入一次,就sleep一秒,然后刷新缓冲区。这样,fp指向的缓冲区将被动态地写入字符串:

初识Linux · 重定向和缓冲区(续)这个过程是动态的,但如果我们去掉fflush,并且在buffer数组中不写入\n,结果就是在log.txt中,只有在程序运行结束,即进程终止后,缓冲区被强制刷新,数据才会显示:

初识Linux · 重定向和缓冲区(续)这一现象表明了用户级别的缓冲区的存在。

使用fflush函数或\n转义字符可以刷新缓冲区,数据刷新后,操作系统会将数据从内核级缓冲区写入磁盘。

这也算是对缓冲区的简单复习。今天的重点是stderr。

我们通过一个问题引出:

平时我们更多使用的是stdin和stdout,对于stderr,我们只知道它与错误有关,那么它的具体表现是什么呢?我们现在来看看。


首先,我们用C++的代码来看看stderr:

int main(){cout 
登录后复制

初识Linux · 重定向和缓冲区(续)为什么这里的cout和cerr打印出来的结果一样呢?

我们再用C语言的stderr和stdout试试:

int main(){    
    fprintf(stdout,"Hello Linux! I am stdout\n");    
    fprintf(stderr,"Hello Linux! I am stderr\n");    
    return 0;
}
登录后复制

初识Linux · 重定向和缓冲区(续)此时结果居然还是一样的,stderr和stdout难道没有区别吗?

并不是,我们试试重定向:

初识Linux · 重定向和缓冲区(续)初识Linux · 重定向和缓冲区(续)使用>时,发现stdout的数据被存放到了log.txt中,而stderr没有。这说明事情有了眉目。

当用户操作计算机时,对数据流动不甚了解,比如报错、输出、输入等信息都需要计算机帮我们完成。依赖的是stdin、stdout和stderr。如果没有报错,stdout和stderr的使用基本相同,但如果有报错信息,我们无法将报错信息重定向到log.txt。这是由于>的真正名称是标准输出重定向符,只重定向标准输出,不会重定向标准错误。因此,如果有如下代码:

int main(){    
    fprintf(stdout,"Hello Linux! I am stdout\n");    
    fprintf(stderr,"Hello Linux! I am stderr\n");    
    fprintf(stderr,"Hello Linux! I am stderr\n");    
    fprintf(stdout,"Hello Linux! I am stderr\n");    
    fprintf(stdout,"Hello Linux! I am stderr\n");    
    fprintf(stderr,"Hello Linux! I am stderr\n");    
    fprintf(stderr,"Hello Linux! I am stderr\n");    
    fprintf(stdout,"Hello Linux! I am stderr\n");    
    fprintf(stderr,"Hello Linux! I am stderr\n");    
    return 0;
}
登录后复制

stdout和stderr的信息混杂在一起,人眼很难分辨。因此,使用标准输出重定向时,可以区分开来:

初识Linux · 重定向和缓冲区(续)标准错误只能打印在显示器上,这也从另一个角度验证了1和2对应的显示器实际上是同一个。

如果我想将1和2的消息都重定向呢?我们可以这样做:

初识Linux · 重定向和缓冲区(续)初识Linux · 重定向和缓冲区(续)这个指令看似有点怪异,但解释起来很容易。进程运行时,1被重定向到log.txt中,2>&1的意思是将1的内容复制到2中,包括文件指针。因此,相当于让2的文件指针也指向了1所指向的文件。

这样,就完成了2的重定向。

同学们有没有用过perror呢?为什么报错时我们使用这个打印,而不是使用printf?这也算是一个回顾,因为perror本质上是向2打印,printf是向1打印,虽然结果一样,但本质不同!

这就是对stderr的理解。

感谢阅读!

以上就是初识Linux · 重定向和缓冲区(续)的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号