Linux操作系统从入门到实战(十一)回车换行问题与用户缓冲区问题
前言
- 前面的博客里我们讲解了Linux开发工具自动化构建-make/Makefile里的基础知识和细节,make/Makefile的推导过程与扩展语法
- 接下来我们继续讲解用户缓冲区问题
我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的Linux知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_12879535.html?spm=1001.2014.3001.5482
一、回车换行问题
在计算机中,“回车”和“换行”是两个源自机械打字机时代的概念,对应两个不同的控制字符,在 Linux 系统中有明确的区分和使用规则。
1. 回车(\r)回到行首
- 含义:
\r
是“Carriage Return”(回车)的缩写,源自机械打字机——当打完一行字后,需要把“打字头”(carriage)拉回到行的开头,才能继续在新的位置打字。 - 效果:在屏幕或终端中,
\r
的作用是让光标直接跳回到当前行的最左侧(不换行)。
举例:如果终端显示
abcdef
,此时输出\r123
,光标会回到行首,然后打印123
,最终显示123def
(123
覆盖了abc
的位置)。
2. 换行(\n)换到下一行
- 含义:
\n
是“Line Feed”(换行)的缩写,同样源自机械打字机——打完一行后,需要把纸向上“喂”一行(换行),才能继续在下一行打字。 - 效果:在屏幕或终端中,
\n
的作用是让光标直接跳到下一行(但默认会同时回到下一行的行首,这是 Linux 的优化)。
举例:如果终端显示
abc
,输出\n123
后,会先换行到下一行,再打印123
,最终显示:
abc
123
3. Linux 中的处理规则
Linux(以及 Unix 系统)对这两个字符的处理非常直接:
- 用
\n
表示“换行+回车”:在 Linux 中,文本文件的换行统一用\n
表示。当程序遇到\n
时,会同时完成“换行(跳到下一行)”和“回车(光标到行首)”的动作(相当于自动补全了\r
的功能)。 \r
仅单独使用:只有在需要单独“回到行首”时(比如动态刷新终端内容,如进度条),才会单独使用\r
。
二、sleep函数是什么?
1. 命令行函数 sleep( )
在Linux的CentOS系统里, sleep是一个系统调用,它的作用是让进程进入休眠状态,休眠时长以秒为单位。
该调用会使进程暂停运行,直到指定的秒数过去,或者进程接收到信号。
- 若休眠时间完整结束,就返回0。
- 要是因接收到信号而提前终止休眠,就返回剩余未休眠的秒数。
这是一个命令行工具,可在shell脚本里使用,用于暂停脚本的执行。
(1)头文件与原型
#include <unistd.h>
unsigned int sleep(unsigned int seconds);
(2)基本用法
sleep NUMBER[SUFFIX]
- 其中,
NUMBER
代表数字,SUFFIX
表示时间单位:s
代表秒(这是默认单位)。m
代表分钟。h
代表小时。d
代表天。
(3)示例
sleep 5 # 暂停5秒
sleep 2m # 暂停2分钟
sleep 1h 30m # 暂停1小时30分钟
3. 代码示例
下面通过一个简单的C++程序来展示 sleep
的使用方法:
#include <iostream>
#include <unistd.h> // 包含 sleep 函数
#include <ctime> // 用于获取当前时间
int main() {
std::cout << "开始休眠... 当前时间: "
<< std::time(nullptr) << std::endl;
// 休眠5秒
unsigned int remaining = sleep(5);
if (remaining == 0) {
std::cout << "休眠了5秒后继续执行。当前时间: "
<< std::time(nullptr) << std::endl;
} else {
std::cout << "休眠被中断,剩余 " << remaining
<< " 秒。当前时间: " << std::time(nullptr) << std::endl;
}
return 0;
}
4. 编译运行
输入下面命令:
g++ -o sleep sleep.cpp
运行程序:
./sleep
三、用户缓冲区问题
1. 代码的执行顺序
- 我们先来看一组代码
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("hello world!");
sleep(2);
return 0;
}
这里代码的执行顺序是:
- 先执行
printf("hello world!")
- 再执行
sleep(2)
- 最后程序退出
不过,我们观察到"hello world!"是在2秒等待之后才显示出来的,这和代码顺序似乎矛盾,这就和C语言的输出缓存机制有关了。
2. 输出缓存机制
C语言中,printf
的内容通常会先被存到一个输出缓冲区里,而不是直接显示在屏幕上。缓冲区刷新到屏幕的时机由系统的刷新策略决定,常见的刷新策略有:
- 行刷新:遇到换行符
\n
时刷新 - 满刷新:缓冲区满时刷新
- 程序退出时刷新
在我们代码里,printf("hello world!")
没有包含换行符\n
,所以内容会暂时停留在输出缓冲区中,直到:
- 后续代码中遇到换行符
- 缓冲区被填满
- 程序退出
而sleep(2)
只是让程序暂停执行2秒,并不会刷新缓冲区,所以"hello world!"会在2秒等待之后,随着程序退出才被显示出来。
3. 手动刷新缓冲区
为了让"hello world!"在sleep(2)
之前就显示出来,可以使用fflush
函数手动刷新缓冲区:
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("hello world!");
fflush(stdout);
sleep(2);
return 0;
}
fflush(stdout)
的作用是强制把标准输出缓冲区里的内容立即刷新到屏幕上,这样在执行sleep(2)
之前,我们就能看到"hello world!"已经显示出来了。
4. 刷新的示例
如果想利用行刷新策略,可以在printf
中加上换行符:
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("hello world!\n");
sleep(2);
return 0;
}
这样"hello world!"会在sleep(2)
之前就显示出来,因为换行符\n
触发了行刷新。
缓冲区机制是为了提高IO效率,而
fflush
给我们提供了手动控制缓冲区刷新的手段,在需要即时显示输出的场景下非常有用。
以上就是这篇博客的全部内容,下一篇我们将继续探索Linux的更多精彩内容。
我的个人主页
欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的Linux知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_12879535.html?spm=1001.2014.3001.5482
非常感谢您的阅读,喜欢的话记得三连哦 |