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

目录

前言:

加深理解

stderr


前言:

本文是重定向和缓冲区的续篇,所以篇幅并不会很长。

本文的主要目标是介绍stderr,对于0 1 即stdin stdout默认打开我们是能够理解的,stderr是什么我们好像并没有使用过?并且本文会加深一下缓冲区的理解和重定向的理解。

那么话不多说,进入正题吧。


加深理解

我们通过一个函数,sprintf来介绍缓冲区,因为sprintf是C语言的函数,而在C语言里面这个函数我们基本上没有使用过,所以学习Linux也有一定程度上介绍了C语言的调用底层的函数。

sprintf的参数是str,后面是正常的printf的参数。

我们可以通过该函数往一个数组里面写入数据:

cpp 复制代码
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指向的缓冲区写入动态的字符串:

这个过程是动态的,但是如果我们将fflush去掉,并且在buffer数组里面不写入\n,我们看到的结果就是log.txt里面是等程序运行完,也就是进程终止之后,强制刷新缓冲区,从而导致的数据刷新出来:

这个点从另一个点,告诉了我们用户级别,也就是语言层面的缓冲区的存在。

而使用函数fllush 转义字符\n都是可以刷新该缓冲区,数据刷新之后,由OS将将数据从内核级别的缓冲区刷新到磁盘里面去。

也算是简单的复习了一下,今天的重点是stderr。

由一个问题引出:

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


stderr

我们先使用C++的代码看看:

cpp 复制代码
int main()
{
	cout << "Hello Linux! I am cout\n" << endl;
	cerr << "Hello Linux! I am cerr\n" << endl;
	return 0;
}

为什么这里的cout 和 cerr打印出来的都是一样的呢?

我们使用C语言的stderr stdout试试:

cpp 复制代码
int main()
{
    fprintf(stdout,"Hello Linux! I am stdout\n");
    fprintf(stderr,"Hello Linux! I am stderr\n");
    return 0;
}

此时结果居然还是一样的,难道stderr和stdout就没有区别了吗?

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

使用>的时候,发现stdout的数据,存放到了log.txt里面,但是stderr并没有,好像事情有点眉目了?

你想,当用户操作计算机的时候,对于数据的流动是不大清晰的,比如报错,比如输出,甚至比如输入的信息都需要计算机帮我们完成,那么借助谁帮我们完成呢?

其实靠的就是stdin stdout stderror,如果没有报错什么的,stdout stderr的用法基本上是一样的,但是如果有报错信息,我们无法将报错信息重定向到log.txt,这是因为>的真正名称叫做标准输出重定向符,也就是只重定向标准输出,对于标准错误是不会重定向的,所以如果有如下代码:

cpp 复制代码
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的信息混在了一起,人眼分辨出来肯定十分费力,所以使用标准输出重定向的时候,就可以分辨出来了:

对于标准错误就只能打印在显示器上,这个点从另一方面也验证了1 2对应的显示器其实是同一个的结果。

那么如果我想要将1 2的消息都重定向呢?我们就可以:

这个指令稍微有点怪异,但是解释起来是很容易的。进程运行的时候,1重定向到了log.txt里面,2>&1的意思是将1的内容拷贝到2里面,包括文件指针。所以相当于让2的文件指针也指向了1所指向的文件。

此时,完成了2的重定向。

那么,同学们有没有用过,perror呢!!为什么报错的时候我们使用这个打印,而不是使用printf打印!!这里也算是一个call back了,因为perror本质是给2打印,printf是给1打印,虽然结果一样,但是本质不同!!

这是对于stderr的理解。


感谢阅读!

相关推荐
猫豆~4 小时前
ceph分布式存储——1day
java·linux·数据库·sql·云计算
前方一片光明4 小时前
SQL SERVER——通过计划任务方式每月对配置数据、审计数据等进行备份
运维·服务器
TFATS4 小时前
Nvidia H100 算力服务器 Cuda Fabric Manager 升级
服务器·postgresql·fabric
小嘟嘟134 小时前
Kurator深度解析:云原生多集群管理的高效解决方案
linux·运维·docker·云原生·自动化
韩曙亮4 小时前
【错误记录】VirtualBox 中安装 Ubuntu 系统无法跨虚拟机进行复制操作 ( 解决方案 - 启用 “ 共享粘贴板 “、“拖动“ 双向操作 )
linux·运维·ubuntu·virtualbox·ros 2
老王熬夜敲代码4 小时前
IO重定向
linux·笔记
大柏怎么被偷了4 小时前
【Linux】重定向与应用缓冲区
linux·服务器·算法
金海境科技4 小时前
【服务器数据恢复】数据中心私有云Ceph分布式集群文件丢失数据恢复案例
服务器·经验分享·分布式·ceph
dodod20124 小时前
Ubuntu24.04.3执行sudo apt install yarnpkg 命令失败的原因
java·服务器·前端
刘一说4 小时前
GeoServer:开源GIS服务器的技术深度解析与OGC标准实践
运维·服务器·开源