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

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,最终显示 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)头文件与原型

c 复制代码
#include <unistd.h>
unsigned int sleep(unsigned int seconds);

(2)基本用法

bash 复制代码
sleep NUMBER[SUFFIX]
  • 其中,NUMBER 代表数字,SUFFIX 表示时间单位:
    • s 代表秒(这是默认单位)。
    • m 代表分钟。
    • h 代表小时。
    • d 代表天。

(3)示例

bash 复制代码
sleep 5      # 暂停5秒
sleep 2m     # 暂停2分钟
sleep 1h 30m # 暂停1小时30分钟

3. 代码示例

下面通过一个简单的C++程序来展示 sleep 的使用方法:

cpp 复制代码
#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. 编译运行

输入下面命令:

bash 复制代码
g++ -o sleep sleep.cpp

运行程序:

bash 复制代码
./sleep


三、用户缓冲区问题

1. 代码的执行顺序

  • 我们先来看一组代码
cpp 复制代码
#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函数手动刷新缓冲区:

cpp 复制代码
#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中加上换行符:

cpp 复制代码
#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

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

相关推荐
不掰手腕2 小时前
在UnionTech OS Server 20 (统信UOS服务器版) 上离线安装PostgreSQL (pgsql) 数据库
linux·数据库·postgresql
Lynnxiaowen3 小时前
今天继续昨天的正则表达式进行学习
linux·运维·学习·正则表达式·云计算·bash
努力学习的小廉3 小时前
深入了解linux系统—— POSIX信号量
linux·运维·服务器
刘一说3 小时前
CentOS部署ELK Stack完整指南
linux·elk·centos
从零开始的ops生活3 小时前
【Day 50 】Linux-nginx反向代理与负载均衡
linux·nginx
IT成长日记3 小时前
【Linux基础】Linux系统配置IP详解:从入门到精通
linux·运维·tcp/ip·ip地址配置
夜无霄3 小时前
安卓逆向(一)Ubuntu环境配置
linux·运维·爬虫·ubuntu
田野里的雨3 小时前
manticore离线安装(Ubuntu )
linux·运维·服务器·全文检索
wanhengidc3 小时前
云手机就是虚拟机吗?
运维·网络·安全·智能手机
Angletank3 小时前
虚拟机中centos简单配置
linux·经验分享·程序人生·centos