当前位置: 首页 > java >正文

Linux操作系统从入门到实战(十一)回车换行问题与用户缓冲区问题

Linux操作系统从入门到实战(十一)回车换行问题与用户缓冲区问题

  • 前言
  • 一、回车换行问题
    • 1. 回车(\r)回到行首
    • 2. 换行(\n)换到下一行
    • 3. Linux 中的处理规则
  • 二、sleep函数是什么?
    • 1. 命令行函数 sleep( )
      • (1)头文件与原型
      • (2)基本用法
      • (3)示例
    • 3. 代码示例
    • 4. 编译运行
  • 三、用户缓冲区问题
    • 1. 代码的执行顺序
    • 2. 输出缓存机制
    • 3. 手动刷新缓冲区
    • 4. 刷新的示例


前言

  • 前面的博客里我们讲解了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,最终显示 123def123 覆盖了 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;
}

这里代码的执行顺序是:

  1. 先执行printf("hello world!")
  2. 再执行sleep(2)
  3. 最后程序退出

不过,我们观察到"hello world!"是在2秒等待之后才显示出来的,这和代码顺序似乎矛盾,这就和C语言的输出缓存机制有关了
在这里插入图片描述

2. 输出缓存机制

C语言中,printf的内容通常会先被存到一个输出缓冲区里,而不是直接显示在屏幕上。缓冲区刷新到屏幕的时机由系统的刷新策略决定,常见的刷新策略有:

  1. 行刷新:遇到换行符\n时刷新
  2. 满刷新:缓冲区满时刷新
  3. 程序退出时刷新

在我们代码里,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

非常感谢您的阅读,喜欢的话记得三连哦

在这里插入图片描述

http://www.xdnf.cn/news/15853.html

相关文章:

  • 通俗易懂神经网络:从基础到实现
  • 学习日志15 python
  • 零基础入门 AI 运维:Linux 部署全栈项目实战(MySQL+Nginx + 私有化大模型)
  • 【1】计算机视觉方法(更新)
  • selenium4 web自动化测试
  • 面向对象基础笔记
  • QFutureInterface和QFuture间联系与区别
  • 《计算机网络》实验报告五 DNS协议分析与测量
  • 两个数据表的故事第 2 部分:理解“设计”Dk
  • ThinkPHP8极简上手指南:开启高效开发之旅
  • 项目案例:苏宁易购评论获取
  • 民法学学习笔记(个人向) Part.1
  • 【智能协同云图库】第一期:用户管理接口设计与功能实现
  • 【Java学习|黑马笔记|Day18】Stream流|获取、中间方法、终结方法、收集方法及其练习
  • 超大整数任意进制之间在线转换工具
  • 剑指offer67_构建乘积数组
  • 周志华《机器学习导论》第11章 特征选择与稀疏学习
  • PyTorch里的张量及张量的操作
  • [前端技术基础]CSS选择器冲突解决方法-由DeepSeek产生
  • 前端的测试
  • 如何实战优化SEO关键词提升百度排名?
  • 深度学习图像分类数据集—百种病虫害分类
  • 【KDD2025】时间序列|Merlin:不固定缺失率下时间序列预测新SOTA!
  • C++ - 仿 RabbitMQ 实现消息队列--服务端核心模块实现(一)
  • 服务器上的文件复制到本地 Windows 系统
  • python网络爬虫小项目(爬取评论)超级简单
  • git fork的项目远端标准协作流程 仓库设置[设置成upstream]
  • 快速上手git
  • LINUX入门(二)QT的安装及运行环境搭建
  • 【实习总结】Qt中如何使用QSettings操作.ini配置文件